我想测试一个处理Bundles的方法。但是,我无法在测试环境中创建(非null)Bundle对象。
给出以下代码:
Bundle bundle = new Bundle();
bundle.putString("key", "value");
boolean containsKey = bundle.containsKey("key");
如果代码在应用程序上下文中执行,则 containsKey
为true
,如果在单元测试中执行,则为false
。
我无法弄清楚为什么会这样,以及如何为我的测试创建一个Bundle。
答案 0 :(得分:15)
如果您的构建脚本包含以下内容:
testOptions {
unitTests.returnDefaultValues = true
}
然后这就是为什么即使你没有为Bundle类指定模拟,你的测试也不会失败的原因。
有几种方法可以解决这个问题:
使用Mockito模拟框架来模拟Bundle类。不幸的是,你必须自己编写很多样板代码。例如,您可以使用此方法来模拟bundle对象,因此它将通过 getString 方法返回正确的值:
@NonNull
private Bundle mockBundle() {
final Map<String, String> fakeBundle = new HashMap<>();
Bundle bundle = mock(Bundle.class);
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
String key = ((String) arguments[0]);
String value = ((String) arguments[1]);
fakeBundle.put(key, value);
return null;
}
}).when(bundle).putString(anyString(), anyString());
when(bundle.get(anyString())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
String key = ((String) arguments[0]);
return fakeBundle.get(key);
}
});
return bundle;
}
使用Robolectric框架为您的单元测试提供某种影子类。这允许您在单元测试中使用Android特定类,并且它们将正常运行。通过使用该框架,您的单元测试将在几乎没有任何变化的情况下正常运行。
我猜你最不受欢迎,但是,这是合格的。您可以使您的测试功能正常,并在您的Android设备或模拟器上运行它。因为速度,我不建议那样。在执行测试之前,您必须构建测试apk,安装并运行。如果您要进行TDD,这是非常慢的。
答案 1 :(得分:1)
使用Mockito,您可以执行以下操作:
one.py
现在,containsKey 在要测试的类中为true。
有关when()的一些其他信息。当使用when()包装模拟对象方法调用时,它将跳过该方法的实际实现,并立即返回thenReturn()部分提供的值。在编写某些单元测试时,这是一个救命稻草,因为一旦方法调用到它的“兔子洞”中,它可能会成为噩梦。
这是我找到的设置通往实际要测试代码的路径的最佳方法。
答案 2 :(得分:0)
我最终使用了Mockito:
// Returns Stackoverflow as it is the only documentation that has the type Q&A
let ref = this.firebase.database().ref().child('documentation').orderByChild('type').equalTo('Q&A').on('value', snap => {
doc = snap.val();
console.log(doc);
});
由于我不需要测试很多在bundle中传递的参数,我嘲笑他们这样的调用:
Bundle extras = mock(Bundle.class);
我向团队提出的建议是用Java模拟替换Bundle用法。