是否可以同时使用 EasyMockSupport
和 EasyMockRule
(或 EasyMockRunner
)时,使用 EasyMockSupport
通过 代表团 而不是继承)?
换句话说:如何使 EasyMockSupport
觉察到自己的嘲讽 EasyMockRule
?
下面是一个MWE演示我所面临的问题。
// Class under test
public class MyClass {
private Collaborator collaborator;
public MyClass() {
collaborator = new Collaborator();
}
// Method under test
public int myMethod() {
return collaborator.mockedMethod() + 1;
}
}
// Class to be mocked
public class Collaborator {
public int mockedMethod() {
return 1;
}
}
// Test case
public class MyClassTest {
private EasyMockSupport easyMockSupport = new EasyMockSupport();
@Rule public EasyMockRule easyMockRule = new EasyMockRule(this);
@TestSubject private MyClass testSubject = new MyClass();
@Mock private Collaborator collaboratorMock;
@Test public void testMyMethod() {
EasyMock.expect(collaboratorMock.mockedMethod()).andReturn(2);
easyMockSupport.replayAll();
int result = testSubject.myMethod();
Assert.assertEquals("Should return 2+1 when successfully mocked", 3, result);
// throws java.lang.AssertionError: expected: <3> but was: <1>
}
}
测试失败,但如果 MyClassTest
延伸 EasyMockSupport
. 但我不能用继承来做我正在做的事情,所以我的问题)。
我对这种行为的理解是,在我的例子中。EasyMockSupport
不知道 Collaborator
嘲讽 replayAll()
没有任何效果,当被调用时,模拟仍处于记录状态。testSubject.myMethod()
(因此 mockedMethod()
返回0).事实上。injectMocks()
文件 说。
如果参数扩展了EasyMockSupport, mocks将使用它来创建,以允许replayAllverifyAll之后工作。
但是当使用授权时,参数(即测试类)并没有扩展到 EasyMockSupport
. 是我遗漏了什么,还是不可能?
附注:我使用的是EasyMock 3.6。理想情况下,我想找到一个解决方案,保持该版本,但随时表明,如果有一个相关的功能bugfix在以后的版本。
提前感谢您的帮助
不容易。然而,这是一个有用的用例,所以我建议你填写一个 "EasyMockSupport"。发出.
同时,我们需要让规则意识到EasyMocksSupport的存在。这里有一个解决方案。
import org.easymock.EasyMock;
import org.easymock.EasyMockRule;
import org.easymock.EasyMockSupport;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.easymock.internal.MocksControl;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import java.lang.reflect.Field;
// Class under test
class MyClass {
private Collaborator collaborator;
public MyClass() {
collaborator = new Collaborator();
}
// Method under test
public int myMethod() {
return collaborator.mockedMethod() + 1;
}
}
// Class to be mocked
class Collaborator {
public int mockedMethod() {
return 1;
}
}
class ExtendedEasyMockSupport extends EasyMockSupport {
public void addMock(Object mock) {
if(EasyMockSupport.getMockedClass(mock) == null) {
throw new IllegalArgumentException(mock + " is not a mock");
}
MocksControl control = MocksControl.getControl(mock);
controls.add(control);
}
public void addAllMocks(Object testClass) {
Field[] fields = testClass.getClass().getDeclaredFields();
for (Field field : fields) {
Mock annotation = field.getAnnotation(Mock.class);
if(annotation != null) {
field.setAccessible(true);
Object mock;
try {
mock = field.get(testClass);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
addMock(mock);
}
}
}
}
// Test case
public class MyClassTest {
private final ExtendedEasyMockSupport easyMockSupport = new ExtendedEasyMockSupport();
@Rule
public EasyMockRule easyMockRule = new EasyMockRule(this);
@TestSubject
private final MyClass testSubject = new MyClass();
@Mock
private Collaborator collaboratorMock;
@Before
public void before() {
easyMockSupport.addAllMocks(this);
}
@Test
public void testMyMethod() {
EasyMock.expect(collaboratorMock.mockedMethod()).andReturn(2);
easyMockSupport.replayAll();
int result = testSubject.myMethod();
Assert.assertEquals("Should return 2+1 when successfully mocked", 3, result);
// throws java.lang.AssertionError: expected: <3> but was: <1>
}
}