当前位置: 首页 > 知识库问答 >
问题:

Mockito验证在第二个单元测试中失败

全冥夜
2023-03-14

我将Mockito与JUnit一起使用,为Android项目中的类实现单元测试。问题是,我在随后的两个测试中调用了Mockito.verify,而这两个测试完全相同(以确保我正确使用了Mockito),但有趣的是,在第二个测试中的verify总是失败。我怀疑,在使用@before注释的每次测试之前需要执行一些操作,而我忽略了这些操作。

我使用Android Studio 3.4.1、Mockito 2.7.22和JUnit 4.12。

@Test
public void test_onStart_do_nothing() throws Exception {
    ZConnectionService zConnectionService = new ZConnectionService();
    ZConnection mockedZConnection = mock(ZConnection.class);

    doNothing().when(mockedZConnection).connect();
    zConnectionService.initConnection(mockedZConnection);

    verify(mockedZConnection, times(1)).connect();
}

@Test
public void test_onStart_throw_IO_exceptioon() throws Exception {
    ZConnectionService zConnectionService = new ZConnectionService();
    ZConnection mockedZConnection = mock(ZConnection.class);

    doNothing().when(mockedZConnection).connect();
    zConnectionService.initConnection(mockedZConnection);
    // Line above is the line that error message points to!

    verify(mockedZConnection, times(1)).connect();
}

下面是测试中的函数

public void initConnection(ZConnection connection) {
    Log.d(TAG,"initConnection()");

    if (mConnection == null) {
        mConnection = connection;
    }

    if (!mActive) {
        mActive = true;

        if (mThread == null || !mThread.isAlive()) {
            mThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    // The code here runs in a background thread.
                    Looper.prepare();
                    mTHandler = new Handler();

                    try {
                        mConnection.connect();
                    } catch (IOException e) {
                        Intent i = null;
                        i = new Intent(ZConnectionService.UI_NOTCONNECTED);
                        i.setPackage(getApplicationContext().getPackageName());
                        getApplicationContext().sendBroadcast(i);

                        e.printStackTrace();

                        // Stop the services all together.
                        stopSelf();
                    }

                    Looper.loop();
                }
            });

            mThread.start();
        }
    }
}

我希望这两项测试都能顺利通过。实际上,当我单独运行它们时,这两个测试都通过了,但当我运行整个套件时,它们失败了,并且错误为:

Wanted but not invoked:
mockedZinkConnection.connect();
-> at com.app.z.ZConnectionServiceUnitTest.test_onStart_throw_IO_exceptioon(ZConnectionServiceUnitTest.java:207)
Actually, there were zero interactions with this mock.

共有1个答案

庾波光
2023-03-14

我认为这是一个多线程的问题。当您调用initconnection时,它会在线程中调用mConnection.connect()。您遇到的问题是,此线程需要一些时间来完成,您最终会在线程实际到达connection()调用之前调用verify(mockedZConnection,times(1)).connect();。确保它的一种方法是在启动线程后加入它,它将等到线程完成后再继续:

mThread.start();
try {
    mThread.join();
} catch (InterruptedException i) {
    i.printStackTrace();

}

现在这两个测试都应该起作用了。

这在代码中当然是不可接受的,因为它否定了线程的使用。您将需要另一种方法来测试它。

我能想到的一种方法是在检查mock之前等待测试中的线程完成:

@Test
public void test_onStart_throw_IO_exceptioon() throws Exception {
    ZConnectionService zConnectionService = new ZConnectionService();
    ZConnection mockedZConnection = mock(ZConnection.class);
    doNothing().when(mockedZConnection).connect();

    zConnectionService.initConnection(mockedZConnection);

    // Wait for the Thread to complete
    while(zConnectionService.mThread.isAlive()) {
        Thread.sleep(100);
    }
    verify(mockedZConnection, times(1)).connect();
}

试过了,对我来说很管用。但我不确定这是一个最佳实践,因为您需要公开类的一些内部内容,这违反了封装

ZConnectionService类上使用包保护的IsThreadAlive()方法可能是可以接受的

boolean isThreadAlive() {
    return mThread.isAlive();
}

和测试中的循环

while(zConnectionService.isThreadAlive()) {
    Thread.sleep(100);
}
 类似资料:
  • 玩弄Mockito来实现我的服务的单元测试,但由于某种原因,我无法通过我的厚脑袋来实现这一点。我的考试通过了,但我不能确信我做得对。 下面是一个测试count()方法的示例。该方法只是将调用转发到它的存储库,我不想验证仅此而已,没有其他事情发生。这就是我得到的: 我的考试及格了,但我有一些问题。 > 我需要验证吗?我觉得我这样做是因为我想验证personRepository。实际上调用了count

  • 我正在尝试测试,只有在调用case的情况下,否则不会调用该方法。 但这会调用我的,并在内抛出空指针。因为我的行为不会调用,所以我如何在不调用的情况下测试它。

  • 问题内容: 我正在使用RestTemplate 方法将正文发布到端点。我需要使用Mockito为我的代码编写测试用例的帮助。返回类型为void,但是可以将其更改为,或者需要进行测试。我已经提到了许多其他文档,但是它们非常笼统,我尝试使用它们,但是由于and和return类型是不同的,所以大多数对我来说都不起作用。。任何建议表示赞赏。谢谢 这是我的Java课 问题答案: 您正在测试MyClass类中

  • 当宽度与期望值不匹配但测试用例通过时,此代码显示“width increct”。如果宽度不相等,我希望测试失败。 2)如何断言/验证元素不存在? 作为一个新手,我尝试了很多我在Google中找到的东西,这里是Stack Overflow--使用Selenium WebDriver with java断言WebElement不存在,Selenium WebDriver--测试元素是否存在等等。我正在

  • 我在java中使用mockito编写单元测试。 这就是我要测试的声明。 电影是电影名称的集合,是识别电影的关键。 我嘲笑了守望者班 Mockito.when(watcher.watch(Matchers.any(Set.class))) “thenReturn”中包括什么??

  • 当一个批处理任务写入数据库的时候,很容易去查询数据去验证结果是否如预期一样。然而,如果批处理任务写入一个文件,验证输出量同样重要。Spring Batch 提供了一个类AssertFile使输出文件的验证变得容易。assertFileEquals方法带了两个文件对象(或者是两个资源对象)和断言,一行一行的,两个文件有相同的上下文。因此,它可能创建了一个文件,有预期的输出和对比之后返回的真实结果: