需要帮助使用Mockito和JUnit4编写单元测试

Kad*_*ari 22 android junit4 mockito

需要帮助使用Mockito和JUnit4编写以下代码的单元测试,

public class MyFragmentPresenterImpl { 
      public Boolean isValid(String value) {
        return !(TextUtils.isEmpty(value));
      }
}
Run Code Online (Sandbox Code Playgroud)

我尝试了以下方法:MyFragmentPresenter mMyFragmentPresenter

@Before
public void setup(){
    mMyFragmentPresenter=new MyFragmentPresenterImpl();
}

@Test
public void testEmptyValue() throws Exception {
    String value=null;
    assertFalse(mMyFragmentPresenter.isValid(value));
}
Run Code Online (Sandbox Code Playgroud)

但它返回以下异常,

java.lang.RuntimeException:未模拟android.text.TextUtils中的方法isEmpty.有关详细信息,请参阅http://g.co/androidstudio/not-mocked.在android.text.TextUtils.isEmpty(TextUtils.java)....

Joh*_*nny 38

由于JUnit TestCase类不能使用Android相关的API,我们必须将其模拟.
PowerMockito嘲笑的静态类.

在测试用例类上方添加两行,

@RunWith(PowerMockRunner.class)
@PrepareForTest(TextUtils.class)
public class YourTest
{

}
Run Code Online (Sandbox Code Playgroud)

和设置代码

@Before
public void setup() {
    PowerMockito.mockStatic(TextUtils.class);
    PowerMockito.when(TextUtils.isEmpty(any(CharSequence.class))).thenAnswer(new Answer<Boolean>() {
        @Override
        public Boolean answer(InvocationOnMock invocation) throws Throwable {
            CharSequence a = (CharSequence) invocation.getArguments()[0];
            return !(a != null && a.length() > 0);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

实现TextUtils.isEmpty()我们自己的逻辑.

此外,在app.gradle文件中添加依赖项.

testCompile "org.powermock:powermock-module-junit4:1.6.2"
testCompile "org.powermock:powermock-module-junit4-rule:1.6.2"
testCompile "org.powermock:powermock-api-mockito:1.6.2"
testCompile "org.powermock:powermock-classloading-xstream:1.6.2"
Run Code Online (Sandbox Code Playgroud)

由于Behelit年代和Exception的回答.


beh*_*lit 7

使用PowerMockito

在类名上面添加它,并包含任何其他CUT类名(测试中的类)

@RunWith(PowerMockRunner.class)
@PrepareForTest({TextUtils.class})
public class ContactUtilsTest
{
Run Code Online (Sandbox Code Playgroud)

将此添加到您的@Before

@Before
public void setup(){
    PowerMockito.mockStatic(TextUtils.class);
    mMyFragmentPresenter=new MyFragmentPresenterImpl();
}
Run Code Online (Sandbox Code Playgroud)

这将使PowerMockito返回TextUtils中方法的默认值

您还必须添加相关的gradle依赖项

testCompile "org.powermock:powermock-module-junit4:1.6.2"
testCompile "org.powermock:powermock-module-junit4-rule:1.6.2"
testCompile "org.powermock:powermock-api-mockito:1.6.2"
testCompile "org.powermock:powermock-classloading-xstream:1.6.2"
Run Code Online (Sandbox Code Playgroud)


Wah*_*Haq 6

这是@Exception提到的已知问题.在我的情况下,我也偶然发现了相同的情况,但在高级开发人员的建议决定使用Strings.isNullOrEmpty()而不是TextUtils.isEmpty().事实证明这是避免它的好方法.

更新:我最好提一下,这个实用功能Strings.isNullOrEmpty()需要Guava库.


Abh*_*hek 5

如果是Android Studio,请将此行添加到gradle文件中。

android{
....
 testOptions {
        unitTests.returnDefaultValues = true
 }
}
Run Code Online (Sandbox Code Playgroud)

  • 默认值为true。将导致textUtils始终返回true。但是在某些情况下,您应该测试一个错误的案例。检查分支的测试覆盖率将漏掉错误的情况。 (4认同)

Exc*_*ion 4

这是一个已知问题,由于 Android 测试基础中的一个条款规定:

您可以使用 JUnit TestCase 类对不调用 Android API 的类进行单元测试。

Log使用或 之类的类时,默认行为是有问题的TextUtils

总结:

  1. android.jar之前是mock的,所以有些Android API返回值可能不符合预期。
  2. JUnit本身是针对java代码的单一度量,所以尽量不要使用Android API方法。

来源: http ://www.liangfeizc.com/2016/01/28/unit-test-on-android/