junit Java Easymock会发出“java.lang.非法状态异常:void方法无法返回值”或“没有对mock的最后调用可用”

xqnpmsa8  于 2022-11-11  发布在  Java
关注(0)|答案(1)|浏览(213)

我们使用EasyMock对Eclipse中的Java应用程序进行JUnit测试。使用类似下面的代码,我们发现了一个奇怪的行为:当运行完整的测试套件(Eclipse项目-〉运行方式-〉JUnit)时,一个测试用例会重复失败。2但是当它独立运行时,它会运行得很好。
接口:

package de.zefiro.java.easymockexception;

public interface Fruit {
    public String fall();
}

测试类别:

package de.zefiro.java.easymockexception;

import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.assertTrue;

import org.junit.BeforeClass;
import org.junit.Test;

public class Newton {
    private static final Fruit APPLE = createNiceMock(Fruit.class);

    @BeforeClass
    public static void SetUpClass() {
        expect(APPLE.fall()).andReturn("Targeting HEAD").anyTimes();
        replay(APPLE);
    }

    @Test
    public void testGravity() {
        String target = APPLE.fall();
        assertTrue("Missed", target.contains("HEAD"));
    }
}

测试套件:

package de.zefiro.java.easymockexception;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(value = Suite.class)
@SuiteClasses( { Newton.class } )
public class ScienceTests { }

在Eclipse项目上运行所有测试--即ScienceTests调用Newton以及直接调用Newton--在上面的小例子中产生了这个异常:

java.lang.IllegalStateException: no last call on a mock available
at org.easymock.Easymock.getControlForLastCall(EasyMock.java:175)

有一个similar question here,但似乎是无关的。
而在我们的真实的测试代码中(类更大,但主要参与者与精简后的示例相同)出现了这样的异常:

java.lang.IllegalStateException: void method cannot return a value
at org.easymock.internal.MocksControl.andReturn(MocksControl.java:101)

我在Google和StackOverflow上都没有找到答案,但现在我自己找到了,所以本着answering your own questions的精神,我将我的发现贴在下面。值得一提的是我找到的这篇文章,尽管它在这个特定的案例中对我没有帮助:EasyMock Cause-Effect Exception Mapping

gcuhipw9

gcuhipw91#

把断点放在初始化APPLE的行和SetUpClass()中我注意到APPLE只被调用了一次,而SetUpClass被调用了两次。这是因为对Newton的第一次引用创建了类并运行了静态初始化器,而JUnit每次运行测试都调用@BeforeClass。在本例中,测试运行了两次:一次作为正常呼叫,一次作为测试套件的一部分。
我不想更改逻辑(即不使用static),而是将static @BeforeClass更改为一个静态初始化块:

public class Newton {

    [...]

    static {
        expect(APPLE.fall()).andReturn("Targeting HEAD").anyTimes();
        replay(APPLE);
    }

    // no @BeforeClass needed anymore

    [...]
}

这解决了我上面的简化测试和真实的测试编码中的问题。
我没有发现是什么不同触发了不同的异常消息,但发现是相同的-- new只被调用了一次,@BeforeClass被调用了多次,并且在第二次运行时失败了。

相关问题