有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用'when/then'mockito调用具有相同参数的另一个方法

我有以下设置:

class Foo{

    public Foo addDate(String str, Date d){
    .....
    }
    public Foo addString(String str){
    .....
    }
}


class Bar{

    private Foo foo;

    public void bar(){

        foo.addDate(x, x);
    }

}


class testBar{

   //test bar()

}

在编写上述用法的测试用例时,我如何使用When/then在调用addDate但使用相同参数时调用addString

使用mock或spy可以进行类似的操作吗

when(foo.addDate("myString", any())).thenReturn(foo.addString("myString"));

共 (2) 个答案

  1. # 1 楼答案

    When writing a test case for the usage of the above, how can I use when/then to call addString whenever addDate is called but using the same argument.

    我不确定你上面说的是什么意思,所以我决定用一个工作示例来介绍我遇到的情况,在注释中是每个测试的系统输出:

    public class TestIt {
    
        @Rule
        public MockitoRule mockitoRule = MockitoJUnit.rule();
    
        // A bit modified version of your class
        public class Foo {
            public Foo addDate(String str, Date d) {
                System.out.println("addDate(..) should not be called, not mocked?");
                return this; // need to return a Foo :)
            }
    
            public Foo addString(String str) {
                System.out.println("addString(\"" + str + "\")");
                return this;
            }
        }
    
        // To call the real method you need the spy so you can mock only
        // methods that needs different functionality 
        @Spy
        private Foo mockFoo;
    
        // answer that uses param in method invocation
        private Answer<Foo> answer = invocation -> 
                mockFoo.addString(invocation.getArgument(0));
        // answer that calls with fixed param, not using the invocation 
        private Answer<Foo> staticAnswer = invocation -> 
                mockFoo.addString("myString");
    
        @Test
        public void testAnswer() {
            System.out.println("testAnswer");
            doAnswer(answer).when(mockFoo).addDate(any(String.class), any(Date.class));
            mockFoo.addDate("add me", new Date());
            // testAnswer
            // addString("add me")
        }
    
        @Test
        public void testStaticAnswer() {
            System.out.println("testStaticAnswer");
            doAnswer(staticAnswer).when(mockFoo).addDate(any(String.class), any(Date.class));
            mockFoo.addDate("add me", new Date());
            // testStaticAnswer
            // addString("myString")        
        }
    
        @Test
        public void testMyString() { // same as Ruben's answer, only react when myString
            System.out.println("testMyString");
            doAnswer(answer).when(mockFoo).addDate(eq("myString"), any(Date.class));
            mockFoo.addDate("add me", new Date());
            mockFoo.addDate("myString", new Date());
            // testMyString
            // addDate(..) should not be called, not mocked?
            // addString("myString")
        }
    
    }
    
  2. # 2 楼答案

    您可以使用thenAnswer,在这里您可以编写一个lambda,将Answer对象作为参数,在这里您可以提取对addDate的调用的参数:

    when(foo.addDate(eq("myString"), any()))
        .thenAnswer(answer -> 
                foo.addString(answer.getArgument(0)));
    

    看一下文档here