Mockito Uri.parse始终返回null

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解决这个问题也是一种有效的技术.

希望这会有所帮助.


Bri*_*ock 6

我通过使用 Roboelectric 测试运行器解决了这个问题。

@RunWith(RobolectricGradleTestRunner::class)
@Config(constants = BuildConfig::class, sdk = intArrayOf(19))
class WeekPageViewModelConverterTests {
...
}
Run Code Online (Sandbox Code Playgroud)

  • 我在 Java 中将其写入上述 Kotlin 的等效方法是:`@RunWith(RobolectricTestRunner.class)``public class ExampleUnitTest {` (2认同)

Fel*_*nde 5

这里的问题是android.jar用于运行单元测试的文件不包含任何实际代码。这种方式android.net.Urinull默认返回并使用

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)


Bri*_*ice 2

问题可能出在Uri类上,因为被测试的代码是静态代码(Uri.parse(...)),Uri在测试环境中可能初始化得很糟糕。请注意,Android SDK 中有两个 uri 类:

我不是 Android 开发人员,但您可能想检查测试环境。