繁体   English   中英

JUnit / Mockito测试由于奇怪的原因而失败

[英]JUnit/Mockito test failing for bizarre reason

我有一个非常简单的方法,正在尝试进行单元测试:

public class MyAntTask extends org.apache.tools.ant.Task {
    public void execute() {
        fire();
    }

    public void fire() {
        // Do stuff
    }
}

我只想编写一个单元测试,以确认调用execute()总是调用fire() ,所以我这样写:

@Test
public void executeCallsFire() {
    //GIVEN
    MyAntTask myTask = Mockito.mock(MyAntTask.class);

    // Configure the mock to throw an exception if the fire() method
    // is called.
    Mockito.doThrow(new RuntimeException("fired")).when(myTask).fire();

    // WHEN
    try {
        // Execute the execute() method.
        myTask.execute();

        // We should never get here; HOWEVER this is the fail() that's
        // being executed by JUnit and causing the test to fail.
        Assert.fail();
    }
    catch(Exception exc) {
        // THEN
        // The fire() method should have been called.
        if(!exc.getMessage().equals("fired"))
            Assert.fail();
    }
}

我猜(我绝不是专家)Mockito通常无法模拟返回void方法,但这是一种解决方法。 您基本上是说“用一个Mock包裹我的对象,无论何时要执行特定方法,该Mock都将始终返回特定的RuntimeException ”。 因此,除了实际执行fire() ,Mockito只是看到它即将执行并抛出异常。 执行已验证? 校验。

它没有通过传递,而是在调用myTask.execute()下方的第一个Assert.fail()处失败。

对于我的一生,我不知道为什么。 这是JUnit给我的巨大堆栈跟踪的前10条左右的行:

java.lang.AssertionError
    at org.junit.Assert.fail(Assert.java:92)
    at org.junit.Assert.fail(Assert.java:100)
    at net.myproj.ant.tasks.MyAntTaskUnitTest.executeCallsFire(MyAntTaskUnitTest.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)

你们有什么想法吗,StackOverflow的Mockito Gurus 提前致谢!

因为myTask是模拟的,所以根本不调用真实对象。 要调用真实对象,请使用间谍。

您可以使用验证来测试是否调用了某个方法,因此不需要例外。

public void executeCallsFire() {
    MyAntTask myTask = Mockito.spy(new MyAntTask());

    myTask.execute();

    Mockito.verify(myTask).fire();
}

想要模拟正在测试的对象似乎并不正确。 通常最好设计测试,以便您验证对另一个对象的调用。

我在这里看到更多设计问题:

  1. 为什么您需要一种行方法并且它们都是公开的?
  2. 模拟是用于模拟依赖关系,而不是用于测试中的类
  3. 如果您将私人身份开火(名字不清楚)。 您不应该测试班级的私人行为

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM