【问题标题】:Mockito mock a method but use its parameters for the mocked returnMockito 模拟一个方法,但使用它的参数来模拟返回
【发布时间】:2016-10-23 22:35:16
【问题描述】:

我想模拟一个方法public Content createChild(String path, String contentType, Map<String,Object> properties)

我想用任何类型的参数调用该方法的方式来模拟它,因此when() 不起作用,因为我必须告诉它该方法应该接收哪些参数才能被实际模拟。

所以我想对任何独立于给定参数的方法调用做出实际反应(使用间谍?),然后调用某种“回调”来返回一个 Content 对象,我想用给定的真实参数一起构建它方法。

我在 Mockito 中找不到支持此功能的特定 API。

【问题讨论】:

    标签: java unit-testing mockito spy


    【解决方案1】:

    你可以使用Matchers:

    你可以试试这样的:

    when(service.createChild(anyString(), anyString(), anyMap()))
         .thenReturn(any(Content.class));
    

    【讨论】:

    • thenReturn(any(Content.class)) 实际上应该做什么?
    • thenReturn(T value) 返回模拟方法的结果。如果您不关心返回的Content,请使用上面的代码。如果你这样做了,那么你可以使用new Content() 或你创建的任何其他Content 对象。
    • 所以它返回一个模拟的内容类?
    • 是的。更准确地说是Stub。它只是意味着:“当 x 被调用时,返回 y”。
    【解决方案2】:

    当然可以。我为此编写了简单的单元测试

    public class MockitoTest {
    
    
        private SampleService sampleService;
    
        @Before
        public void setUp() throws Exception {
            sampleService = Mockito.mock(SampleService.class);
        }
    
        @Test
        public void mockitoTest() throws Exception {
            when(sampleService.createChild(anyString(), anyString(), anyMapOf(String.class, Object.class)))
                .thenAnswer(invocationOnMock -> {
                    //Here you can build result based on params
                    String pathArg = (String) invocationOnMock.getArguments()[0];
                    if (pathArg.equals("p1")) {
                        return new Content("Content for p1");
                    } else if (pathArg.equals("p2")) {
                        return new Content("Content for p2");
                    } else {
                        return invocationOnMock.callRealMethod();
                    }
                });
    
            Content content = sampleService.createChild("p1", "any", new HashMap<>());
            assertEquals("Content for p1", content.getData());
    
            content = sampleService.createChild("p2", "any", new HashMap<>());
            assertEquals("Content for p2", content.getData());
    
            content = sampleService.createChild("whatever", "any", new HashMap<>());
            assertEquals("original", content.getData());
    
        }
    
        /**
         * Sample service with method
         */
        private static class SampleService {
    
            public Content createChild(String path, String contentType, Map<String, Object> properties) {
                return new Content("original");
            }
    
        }
    
        /**
         * Content example
         */
        private static class Content {
    
            private String data;
    
            Content(String data) {
                this.data = data;
            }
    
            String getData() {
                return data;
            }
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      你可以使用匹配器

      MyClass m = mock(MyClass.class);
      when(m.createChild(any(String.class), any(String.class), any(Map.class))).thenReturn(new Content());
      

      你应该也可以这样使用参数

      when(m.createChild(any(String.class), any(String.class), any(Map.class))).thenAnswer(
             new Answer<Content>()
             {
                 @Override
                 public Content answer(final InvocationOnMock invocation) throws Throwable
                 {
                     return new Content((String) invocation.getArguments()[0], 
      (String) invocation.getArguments()[1],
      (Map) invocation.getArguments()[2]);
                     }
                 }
             }
             );
      

      【讨论】:

        【解决方案4】:

        您可以根据自己的要求尝试使用 eq()any()

        when(service.createChild(eq("helloe/hi"), any(String.class), any(Map.class)))
             .thenReturn(any(Content.class));
        

        eq - 如果我们想为参数使用特定值,那么我们可以使用 eq() 方法。

        any - 有时我们想模拟给定类型的任何参数的行为

        【讨论】:

          猜你喜欢
          • 2020-01-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多