【问题标题】:Mock inner instance on class to test在类上模拟内部实例以进行测试
【发布时间】:2015-12-07 10:43:52
【问题描述】:

我正在使用 Mockito 编写一些测试用例。我遇到一个问题,我在网上寻找解决方案,但没有找到明确的答案。

鉴于以下类,我想模拟对方法 getMessage 的所有调用 在此类型的所有实例上的 ClassB 上。

public class ClassA {
    private ClassB b = new ClassB("From ClassA");

    int methodToTest() {
        System.out.println("methodToTest use instqnce ClassB " + b.getMessage());
        return -1;
    }
}

class ClassB {
    private String message;

    /**
     * 
     */
    public ClassB(final String msg) {
        this.message = msg;
    }

    /**
     * @return the message
     */
    public String getMessage() {
        return message;
    }

    /**
     * @param message the message to set
     */
    public void setMessage(final String message) {
        this.message = message;
    }
}

我试过但没用的如下:

public class ClassATest {

    @Test
    public void testOK1() {
       ArgumentCaptor<ClassB> captorClassB = ArgumentCaptor.forClass(ClassB.class);
       Mockito.doReturn("MOCK message").when(captorClassB.capture()).getMessage();

       ClassA a = new ClassA();
       assertTrue(a.methodToTest() == -1);
    }

    @Test
    public void testOK2() {
        Mockito.doReturn("MOCK message").when(Mockito.any(ClassB.class)).getMessage();

        ClassA a = new ClassA();
        assertTrue(a.methodToTest() == -1);
    }
}

我的问题首先是它是否可能。其次,怎么做?我要重构代码吗?

【问题讨论】:

    标签: unit-testing junit mocking refactoring


    【解决方案1】:

    要创建一个新的 ClassB,您应该在 ClassA 的构造函数中传递一个 ClassB。通过这种方式,您可以传递模拟的 ClassB 实例并验证它是否被调用。

    public class ClassA { 
        ClassB classB;
    
        public ClassA(ClassB classB){
            this.classB = classB;
        }
    }
    

    【讨论】:

    • 嗨,我明白了。如果 ClassB 类型的实例由另一个类提供给 ClassA 类怎么办: int methodToTest() {b = classC.getB(); System.out.println("methodToTest 使用 instqnce ClassB " + b.getMessage());返回-1; }
    • 在这种情况下,我建议您将 classC 作为参数传递(或传递给函数或类),在测试中创建一个继承自 classC 的新类并将方法 getB 覆盖为返回你想要的 ClassB。
    • public class ClassATest { //.... Your tests here.... } static class ClassCMock extends ClassC { public ClassB getB(){ return mockedClassB; } }
    【解决方案2】:

    最后我提出了以下解决方案。如果这种方法有一些缺点,请指出。

    public class ClassA {
        private ClassB b = new ClassB("From ClassA");
    
        int methodToTest() {
            System.out.println("methodToTest use instqnce ClassB " + getClassB().getMessage());
            return -1;
        }
    
        /**
         * 
        */
        public ClassB getClassB() {
            return b;
    
       }
    }
    
    
    
    class ClassB {
        private String message;
    
        /**
         * 
         */
        public ClassB(final String msg) {
            this.message = msg;
        }
    
        /**
         * @return the message
         */
        public String getMessage() {
            return message;
        }
    
        /**
         * @param message the message to set
         */
        public void setMessage(final String message) {
            this.message = message;
        }
    }
    
    
    public class ClassATest {
    
        @Test
        public void testOK() {
            ClassA a = new ClassA();
    
            ClassB b = new ClassB("MOCK message");
    
            ClassA spyA = spy(a);
    
            Mockito.doReturn(b).when(spyA).getClassB();
    
            assertTrue(spyA.methodToTest() == -1);
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2019-10-06
      • 2013-07-08
      • 2017-04-27
      • 2012-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-27
      • 1970-01-01
      相关资源
      最近更新 更多