我正在使用GCM(Google云消息传递)向Android应用发送通知。我的服务器正在使用Google提供的gcm-server.jar
,我正在关注documentation。我可以毫无问题地向设备发送通知。
现在,我正在尝试根据PushNotificationDaoGcmImpl
的私有方法sendNotificationToServer
返回的Result
(source)对业务逻辑进行单元测试。
我知道Result
不能被模拟,因为它是final
类,并且只是将它实例化为new Result()
将无效,因为没有公共构造函数。 Result
内部Builder
类在package com.google.android.gcm.server;
之外无法访问,因此我无法以这种方式构建对象。
我找不到创建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
}
答案 0 :(得分: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);
}
答案 1 :(得分: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
}
}
对我来说,这比处理反思更容易管理。