如何通过 EasyMockRule 或 EasyMockRunner 委托来使用 EasyMockSupport?
How to use EasyMockSupport through delegation with EasyMockRule or EasyMockRunner?
在通过委派(而不是继承)使用EasyMockSupport
时,是否可以同时利用EasyMockSupport
and EasyMockRule
(or EasyMockRunner
)?
换句话说:如何让 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()
documentation 说:
If the parameter extends EasyMockSupport, the mocks will be created using it to allow replayAll/verifyAll to work afterwards
但是当使用委托时,参数(即测试 class)不会扩展 EasyMockSupport
。有没有我遗漏或不可能的东西?
旁注:我正在使用 EasyMock 3.6。理想情况下,我想找到一个保留该版本的解决方案,但请随时指出在以后的版本中是否有相关的 feature/bugfix。
在此先感谢您的帮助!
不容易。但是,这是一个有用的用例,因此我建议您填写 issue.
同时,我们需要让规则知道 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>
}
}
在通过委派(而不是继承)使用EasyMockSupport
时,是否可以同时利用EasyMockSupport
and EasyMockRule
(or EasyMockRunner
)?
换句话说:如何让 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()
documentation 说:
If the parameter extends EasyMockSupport, the mocks will be created using it to allow replayAll/verifyAll to work afterwards
但是当使用委托时,参数(即测试 class)不会扩展 EasyMockSupport
。有没有我遗漏或不可能的东西?
旁注:我正在使用 EasyMock 3.6。理想情况下,我想找到一个保留该版本的解决方案,但请随时指出在以后的版本中是否有相关的 feature/bugfix。
在此先感谢您的帮助!
不容易。但是,这是一个有用的用例,因此我建议您填写 issue.
同时,我们需要让规则知道 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>
}
}