Mockito Uri.parse始终返回null

时间:2015-08-16 13:36:46

标签: android unit-testing 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;
}

我有这个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);
}

但似乎一旦代码运行并且它到达Uri.parse(url),我得到一个空指针。我错过了什么?在生产中,这非常有效。只有在测试时,Uri.parse()才会返回null。

谢谢!

8 个答案:

答案 0 :(得分:17)

最终我在Mockito上使用了PowerMock来模拟Uri类。 使用这些依赖项添加它:

'org.powermock:powermock-api-mockito:1.4.12'
'org.powermock:powermock-module-junit4:1.6.2'

了解它here

它使您可以模拟静态方法,私有方法,最终类等。 在我的测试方法中,我使用了:

PowerMockito.mockStatic(Uri.class);
Uri uri = mock(Uri.class);

PowerMockito.when(Uri.class, "parse", anyString()).thenReturn(uri);

这传递了实际代码中的行并返回了一个Mocked Uri对象,因此测试可以向前移动。 请务必添加:

@RunWith(PowerMockRunner.class)
@PrepareForTest({Uri.class})

作为测试类名称之上的注释。

使用Robolectric解决这个问题也是一种有效的技术。

希望这会有所帮助。

答案 1 :(得分:3)

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

android {
  // ...
  testOptions { 
    unitTests.returnDefaultValues = true
  }
}

不会解决此情况的问题,因为方法的默认返回值仍为null

我的解决方案是使用Unmock插件,其唯一目的是取消android.jar中的某些类/包,并为这些提供完整的实现。

在这种特定情况下,只需将代码段添加到build.gradle文件

即可
apply plugin: 'de.mobilej.unmock'
 //...
unMock {
    keepStartingWith "android.net.Uri"
}

答案 2 :(得分:2)

我使用Roboelectric测试跑步者来解决这个问题。

{{1}}

答案 3 :(得分:2)

我能够使用 android.net.Uri 使用 AndroidJUnit4 runner 如下

import androidx.core.net.toUri
import androidx.test.ext.junit.runners.AndroidJUnit4
...
@RunWith(AndroidJUnit4::class)
class FileTest {
  @get:Rule(order = 0)
  val tempFolder = TemporaryFolder()
  private lateinit var tempFile: File

  @Before
  fun setup() {
    tempFile = tempFolder.newFile()
  }

  @Test
  fun test_fileUri_not_null() {
    assertTrue(tempFile.exists())
    assertNotNull(tempFile.toUri())
  }
}

以上测试写在tests目录下

答案 4 :(得分:1)

问题可能在于Uri类,因为正在测试的代码是静态代码(Uri.parse(...)),Uri可能在测试环境中严重初始化。请注意Android SDK中有两个uri类:

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

答案 5 :(得分:1)

如果您使用android.net.Uri类,那么您需要在Mockito之上使用Robolectric(http://robolectric.org)运行测试

答案 6 :(得分:1)

我在使用android.net.Uri类进行测试时遇到了类似的问题。

我已经解决了将测试从'test'文件夹移动到'androidTest'并在设备中运行它的问题。在设备中,Uri类的行为正常。

答案 7 :(得分:0)

我通过使用“ @RunWith(RobolectricTestRunner :: class)”运行测试套件解决了该问题。

相关问题