【问题标题】:How to use EasyMockSupport through delegation with EasyMockRule or EasyMockRunner?如何通过 EasyMockRule 或 EasyMockRunner 委托使用 EasyMockSupport?
【发布时间】:2020-05-04 14:08:20
【问题描述】:

通过委托(而不是继承)使用EasyMockSupport时,是否可以同时利用EasyMockSupportEasyMockRule(或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() 无效,并且在 @987654337 中调用模拟仍处于记录状态@(因此 mockedMethod() 返回 0)。 确实,injectMocks() documentation 说:

如果参数扩展了 EasyMockSupport,将使用它创建模拟,以允许 replayAll/verifyAll 之后工作

但是当使用委托时,参数(即测试类)不会扩展EasyMockSupport。有什么我遗漏的还是不可能的?

旁注:我使用的是 EasyMock 3.6。理想情况下,我想找到一个保留该版本的解决方案,但请随时指出在以后的版本中是否有相关的功能/错误修复。

提前感谢您的帮助!

【问题讨论】:

    标签: java unit-testing testing easymock


    【解决方案1】:

    不容易。不过这是一个有用的用例,所以我建议您填写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>
        }
    }
    

    【讨论】:

    • 非常感谢!在 EasyMock 提供支持之前,我将使用您的解决方案。 :) 我填写了an issue BTW。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 2021-10-25
    • 2019-11-24
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    相关资源
    最近更新 更多