Java服务器端单元测试GCM结果

3

我正在使用GCM(Google Cloud Messaging)向Android应用发送通知。我的服务器使用由Google提供的gcm-server.jar,并遵循文档。我能够无问题地向设备发送通知。

现在,我正在尝试基于来自PushNotificationDaoGcmImpl的私有方法sendNotificationToServer返回的Result来源)进行业务逻辑的单元测试。

我知道Result不能被Mock,因为它是一个final类,而简单实例化new Result()也不起作用,因为没有公共构造函数。 Result内部的Builder类无法在包外访问,因此我无法以这种方式构建对象。

我无法找到一个好的方法来创建一个Result,这是从Sender(source)返回的内容。
我的问题是,我该如何对PushNotificationDaoGcmImpl进行单元测试,以确保它能够处理基于Result的某些条件?
public class PushNotificationDaoGcmImpl{

    //method I'm trying to test
    public void sendPushNotification(){
        // builds message to send

        Result result = this.sendNotificationToServer(gcmMessage, deviceToken)

        //handle result's error conditions
    }

    //method call I'm trying to mock
    private Result sendNotificationToServer(Message gcmMessage, String deviceToken){
        return gcmSender.send(gcmMessage, deviceToken, 1);
    }
}   

//test snipet
@Test
public void testSendNotificationToServer () throws Exception {
    Result result = new Result();

    PushNotificationMessage message = new PushNotificationMessage("123", "Test", "deviceToken", "Android");

    //Having issue with how to handle Result here
    doReturn(result).when(gcmPushNotificationDaoSpy).sendNotificationToServer(any(Message.class), anyString());

    PushNotificationResult result = gcmPushNotificationDaoSpy.sendPushNotification(message);

    //verify business logic was correct based on Result
}
2个回答

2
我想到的解决方案是使用反射来创建一个Result对象。我不确定这是否是一个很好的方法,但我能够根据不同的Result错误代码测试业务逻辑。
@Test
public void testSendNotificationToServer () throws Exception {
    String successIndicator = null;
    Result result = buildFauxResult("messageId", "deviceToken", successIndicator);

    PushNotificationMessage message = new PushNotificationMessage("123", "Test", "deviceToken", "Android");

    //Having issue with how to handle Result here
    doReturn(result).when(gcmPushNotificationDaoSpy).sendNotificationToServer(any(Message.class), anyString());

    PushNotificationResult result = gcmPushNotificationDaoSpy.sendPushNotification(message);

    //verify business logic was correct based on Result
}

public Result buildFauxResult (String messageId, String canonicalRegistrationId, String errorCode) throws Exception {
           Class <?> builderClass = Class.forName("com.google.android.gcm.server.Result$Builder");
           Constructor <?> builderConstructor = builderClass.getDeclaredConstructors()[0];
           ReflectionUtils.makeAccessible(builderConstructor);
           Object builderObject = builderConstructor.newInstance();

           Method canonicalRegistrationIdMethod = builderClass.getMethod("canonicalRegistrationId", String.class);
           ReflectionUtils.makeAccessible(canonicalRegistrationIdMethod);
           builderObject = ReflectionUtils.invokeMethod(canonicalRegistrationIdMethod, builderObject, canonicalRegistrationId);

           Method messageIdMethod = builderClass.getMethod("messageId", String.class);
           ReflectionUtils.makeAccessible(messageIdMethod);
           builderObject = ReflectionUtils.invokeMethod(messageIdMethod, builderObject, messageId);

           Method errorCodeMethod = builderClass.getMethod("errorCode", String.class);
           ReflectionUtils.makeAccessible(errorCodeMethod);
           builderObject = ReflectionUtils.invokeMethod(errorCodeMethod, builderObject, errorCode);

           Method buildMethod = builderClass.getMethod("build");
           ReflectionUtils.makeAccessible(buildMethod);

           return (Result) ReflectionUtils.invokeMethod(buildMethod, builderObject);
    }

2

您还可以在com.google.android.gcm.server包中创建一个MockResult类,这将使您可以访问Builder。

package com.google.android.gcm.server;

class MockResult {

    public static Result mockResult(...) {
      // Use Builder here to construct Result
    }

}

对我来说,这比处理反射更容易管理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接