与argThat匹配仅适用于具有单个参数的方法吗? [英] Does matching with argThat only work for methods with a single argument?

查看:126
本文介绍了与argThat匹配仅适用于具有单个参数的方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在被测类中,我有以下方法调用:

I have the following method invocation in my class under test:

class ClassUnderTest {
   [...]
    restTemplate.getForEntity(url, MyResponseEntity.class, parameterMap);
   [...]
}

在包含此行的类的单元测试中,我想对getForEntity方法存根,以便它为parameterMap中的不同条目返回不同的响应. 使用BDDMockito,我尝试通过使用

In the unit test of the class containing this line, I want to stub the getForEntity method such that it returns different responses for different entries in the parameterMap. Using BDDMockito, I'm trying to match that the desired parameter is part of the parameterMap by using argThat:

@InjectMocks
private ClassUnderTest classUnderTest;

@Mock
private RestTemplate restTemplate;

[...]

given(restTemplate.getForEntity(anyString(), any(Class.class), argThat(hasEntry("myKey", "myValue"))
   .willReturn(responseEntityA);

但是,如果我运行测试以使parameterMap包含(我在调试器中对此进行了验证)一个键"myKey"和一个值"myValue",则我会得到一个NullPointerException,因为嘲笑似乎没有能够将方法调用与我创建的存根进行匹配.

However, if I run the test such that the parameterMap contains (I verified this in the debugger) a key "myKey" and a value "myValue", I get a NullPointerException, because mockito does not seem to be able to match the method call with the stub I created.

另一方面,通过使用以下非常笼统的匹配,我可以通过为 all 调用提供默认响应来在没有NPE的情况下运行测试,但是不允许我为给定的参数.

On the other hand, using the following very general matching allows me run my tests without NPE, by providing a default response for all calls, however it does not allow me to define a custom response for a given parameter.

given(restTemplate.getForEntity(anyString(), any(Class.class), anyMap())
  .willReturn(defaultResponseEntity);

这是什么原因? argThat仅适用于具有单个参数的方法吗? 有没有另一种方法可以将getEntity的调用与包含特定(键,值)对的映射相匹配?

What is the reason for this? Does argThat only work for methods with a single parameter? Is there another way to match calls of the getEntity with a map that contains a certain (key, value) pair?

推荐答案

argThat当然适用于多个参数,并且您尝试执行的操作显然没有错.我有一个的预感,那就是选择

argThat certainly works for more than one parameter, and there's nothing obviously wrong with what you're trying to do. I have a nagging hunch that it's selecting the wrong overload:

getForEntity(String url, Class<T> responseType, Map<String,?> urlVariables)
getForEntity(String url, Class<T> responseType, Object... urlVariables)

如果泛型不完全匹配,则Java可能会假定您的hasEntryObject...方法最匹配,而anyMapMap<String, ?>匹配.在这种情况下,您将对未调用的重载进行存根(Object...),而Mockito将恢复为您在被测系统中实际调用的重载的默认返回值(Map<String, ?>).将鼠标悬停在您的IDE中的方法调用上可能会揭示出编译器正在匹配的重载.

If the generics don't exactly match, Java may assume that your hasEntry best matches the Object... method where your anyMap matched the Map<String, ?>. In that case, you would be stubbing an overload you're not calling (Object...), and Mockito would revert to default return values for the one you're actually calling in your system under test (Map<String, ?>). Hovering over the method call in your IDE may shed light on which overload the compiler is matching.

要给Java一个更好的提示,请尝试进行如下所示的强制转换(警告,未经测试或验证):

To give Java a better hint, try a cast, which would look like this (warning, not tested or verified):

given(restTemplate.getForEntity(
         anyString(),
         any(Class.class),
         (Map<String, ?>) argThat(hasEntry("myKey", "myValue"))))
    .willReturn(responseEntityA);    

这篇关于与argThat匹配仅适用于具有单个参数的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆