这两个单元测试是相同的,但模拟对象utility
仅在第一个测试中接收到调用。调用模拟doTheThing()
的方法按预期运行。为什么在两个测试中模拟对象utility
都没有收到呼叫?
我已经进行了这些测试
我正在使用Easy Mock 4.0.2和Junit 4.12。
ComponentTest类
import static org.easymock.EasyMock.anyString;
import static org.easymock.EasyMock.expect;
import org.easymock.EasyMockRunner;
import org.easymock.EasyMockSupport;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(EasyMockRunner.class)
public class ComponentTest extends EasyMockSupport {
@TestSubject
private Component component = new Component();
@Mock
private Utility utility;
@Test
public void testDoTheThing1() {
Context.setUtility(utility);
expect(utility.doSomethingWith(anyString())).andReturn(null);
replayAll();
component.doTheThing("aa");
verifyAll();
resetAll();
}
@Test
public void testDoTheThing2() {
Context.setUtility(utility);
expect(utility.doSomethingWith(anyString())).andReturn(null);
replayAll();
component.doTheThing("aa");
verifyAll();
resetAll();
}
}
组件类
public class Component implements Processor{
public String doTheThing(String request) {
return UTILITY.doSomethingWith(request);
}
}
处理器接口
public interface Processor {
Utility UTILITY = Context.getUtility();
}
上下文类
public class Context {
private static Utility utility;
public static Utility getUtility(){
return utility;
}
public static void setUtility(Utility utility) {
Context.utility = utility;
}
}
实用程序类
public class Utility {
public String doSomethingWith(String request) {
return null;
}
}
Junit输出
There was 1 failure:
1) testDoTheThing2(ComponentTest)
java.lang.AssertionError:
Expectation failure on verify:
Utility.doSomethingWith(<any>): expected: 1, actual: 0
at org.easymock.internal.MocksControl.verify(MocksControl.java:242)
at org.easymock.EasyMockSupport.verifyAll(EasyMockSupport.java:523)
at ComponentTest.testDoTheThing2(ComponentTest.java:41)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.junit.runner.JUnitCore.runMain(JUnitCore.java:77)
at org.junit.runner.JUnitCore.main(JUnitCore.java:36)
答案 0 :(得分:1)
来自:https://docs.oracle.com/javase/tutorial/java/IandI/interfaceDef.html
接口中定义的所有常量值都是隐式的public,static和final。
因此,当运行每个测试方法时都会创建一个新的Utility模拟,而Processor.UTILITY隐式是一个静态最终常量,它将仅保留其第一个分配的值-该值将是第一个单元测试的值。
因此,您应该使用“ static final Utility”代替@Mock Utility,并在所有测试方法中使用该单个实例。
要添加的编辑:请注意,在运行每个单独的测试方法之前,每个测试都会重新创建带有@TestSubject和@Mock注释的每个类成员,并将这些新的模拟物注入到新的测试主题中。这样可以最大程度地减少状态/行为从一个测试到另一个测试的影响。巧合的是,Mockito也这样做。