Alo*_*ski 8 testing android unit-testing mocking
我有这种制作方法:
public boolean onShouldOverrideUrlLoading(String url) {
boolean isConsumed = false;
if (url.contains("code=")) {
Uri uri = Uri.parse(url);
String authCode = uri.getQueryParameter("code");
mView.authCodeObtained(authCode);
isConsumed = true;
}
return isConsumed;
}
Run Code Online (Sandbox Code Playgroud)
我有这个Mockito测试方法:
@Test
public void onShouldOverrideUrlLoadingOnAuthCodeObtained(){
String code = "someCode";
boolean isConsumed = mPresenter.onShouldOverrideUrlLoading("http://localhost/?code=" + code);
verify(mView, times(1)).authCodeObtained(code);
assertEquals(isConsumed, true);
}
Run Code Online (Sandbox Code Playgroud)
但似乎一旦代码运行并且它到达Uri.parse(url),我得到一个空指针.我错过了什么?在生产中,这非常有效.只有在测试时,Uri.parse()才会返回null.
谢谢!
Alo*_*ski 17
最终我在Mockito上使用了PowerMock来模拟Uri类.使用这些依赖项添加它:
'org.powermock:powermock-api-mockito:1.4.12'
'org.powermock:powermock-module-junit4:1.6.2'
Run Code Online (Sandbox Code Playgroud)
在这里阅读它.
它使您可以模拟静态方法,私有方法,最终类等.在我的测试方法中,我用过:
PowerMockito.mockStatic(Uri.class);
Uri uri = mock(Uri.class);
PowerMockito.when(Uri.class, "parse", anyString()).thenReturn(uri);
Run Code Online (Sandbox Code Playgroud)
这传递了实际代码中的一行并返回了一个Mocked Uri对象,因此测试可以向前移动.确保添加:
@RunWith(PowerMockRunner.class)
@PrepareForTest({Uri.class})
Run Code Online (Sandbox Code Playgroud)
作为测试类名称之上的注释.
使用Robolectric解决这个问题也是一种有效的技术.
希望这会有所帮助.
我通过使用 Roboelectric 测试运行器解决了这个问题。
@RunWith(RobolectricGradleTestRunner::class)
@Config(constants = BuildConfig::class, sdk = intArrayOf(19))
class WeekPageViewModelConverterTests {
...
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是android.jar用于运行单元测试的文件不包含任何实际代码。这种方式android.net.Uri将null默认返回并使用
android {
// ...
testOptions {
unitTests.returnDefaultValues = true
}
}
Run Code Online (Sandbox Code Playgroud)
不会解决这种情况的问题,因为方法的默认返回值仍然null
我的解决方案是使用Unmock插件,其唯一目的是取消模拟某些类/包android.jar并为其提供完整的实现。
在这种特定情况下,只需将代码片段添加到您的build.gradle文件中
apply plugin: 'de.mobilej.unmock'
//...
unMock {
keepStartingWith "android.net.Uri"
}
Run Code Online (Sandbox Code Playgroud)
问题可能出在Uri类上,因为被测试的代码是静态代码(Uri.parse(...)),Uri在测试环境中可能初始化得很糟糕。请注意,Android SDK 中有两个 uri 类:
我不是 Android 开发人员,但您可能想检查测试环境。