Java Mockito - thenReturn 总是返回空对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26680678/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mockito - thenReturn always returns null object
提问by risingTide
I'm trying to implement Mockito to test a particular method but the .thenReturn(...) seems to always be returning a null object instead of what I intended:
我正在尝试实现 Mockito 来测试特定方法,但 .thenReturn(...) 似乎总是返回一个空对象而不是我想要的:
CUT:
切:
public class TestClassFacade {
// injected via Spring
private InterfaceBP bpService;
public void setBpService(InterfaceBP bpService) {
this.bpService = bpService;
}
public TestVO getTestData(String testString) throws Exception {
BPRequestVO bpRequestVO = new BPRequestVO();
bpRequestVO.setGroupNumber(testString) ;
bpRequestVO.setProductType("ALL") ;
bpRequestVO.setProfileType("Required - TEST") ;
IBPServiceResponse serviceResponse = bpService.getProduct(bpRequestVO); //PROBLEM
if (serviceResponse.getMessage().equalsIgnoreCase("BOB")) {
throw new Exception();
} else {
TestVO testVO = new TestVO();
}
return testVO;
}
}
Spring Configuration:
弹簧配置:
<bean id="testClass" class="com.foo.TestClassFacade">
<property name="bpService" ref="bpService" />
</bean>
<bean id="bpService" class="class.cloud.BPService" />
Mockito Test Method:
Mockito 测试方法:
@RunWith(MockitoJUnitRunner.class)
public class BaseTest {
@Mock BPService mockBPService;
@InjectMocks TestClassFacade mockTestClassFacade;
private String testString = null;
private BPRequestVO someBPRequestVO = new BPRequestVO();
private IBPServiceResponse invalidServiceResponse = new BPServiceResponse();
@Test (expected = Exception.class)
public void getBPData_bobStatusCode_shouldThrowException() throws Exception {
invalidServiceResponse.setMessage("BOB");
someBPRequestVO.setGroupNumber(null);
someBPRequestVO.setProductType("ALL");
someBPRequestVO.setProfileType("Required - TEST");
System.out.println("1: " + someBPRequestVO.getGroupNumber());
System.out.println("2: " + someBPRequestVO.getProductType());
System.out.println("3: " + someBPRequestVO.getProfileType());
System.out.println("4: " + someBPRequestVO.getEffectiveDate());
when(mockBPService.getProduct(someBPRequestVO)).thenReturn(invalidServiceResponse);
mockTestClassFacade.getTestData(testString);
verify(mockBPService).getProduct(someBPRequestVO);
}
}
System output:
系统输出:
1: null
2: ALL
3: Required - TEST
4: null
What's happening here is that when I run the test the serviceResponse object is null on the line in the CUT marked with //PROBLEM above. My desire is to have that object be populated with my "invalidServiceResponse" object from my test method. Judging from the output of my System.out.println's it appears that my bpRequestVO matches my someBPRequestVO in content.
这里发生的事情是,当我运行测试时,上面标有 //PROBLEM 的 CUT 行上的 serviceResponse 对象为空。我的愿望是用我的测试方法中的“invalidServiceResponse”对象填充该对象。从我的 System.out.println 的输出来看,我的 bpRequestVO 似乎与我的 someBPRequestVO 在内容上相匹配。
Could some one show me what I'm missing here?
有人可以告诉我我在这里缺少什么吗?
Thanks for your time!
谢谢你的时间!
采纳答案by lewthor
The instance of BPRequestVO that you use with when()
is different than the one used in getTestData()
.
Unless you override equals()
, they will not match.
BPRequestVO,你有使用实例when()
比所使用的不同getTestData()
。
除非您覆盖equals()
,否则它们将不匹配。
You should not need to write a custom Matcher if you override equals(). Note the following from the Mockito documentation:
如果覆盖 equals(),则不需要编写自定义匹配器。请注意Mockito 文档中的以下内容:
"Custom argument matchers can make the test less readable. Sometimes it's better to implement equals() for arguments that are passed to mocks (Mockito naturally uses equals() for argument matching). This can make the test cleaner."
“自定义参数匹配器可以降低测试的可读性。有时最好为传递给模拟的参数实现 equals()(Mockito 自然使用 equals() 进行参数匹配)。这可以使测试更清晰。”
回答by fge
The problem is in your usage of when()
.
问题在于您对when()
.
You submit a reference to a constructed instance; as a result, the mocking will return what you want only if the argument passed to the method is the same reference.
您提交对构造实例的引用;因此,只有当传递给方法的参数与引用相同时,模拟才会返回您想要的内容。
What you want is an argument matcher; something like:
你想要的是一个参数匹配器;就像是:
when(mockBPService.getProduct(argThatMatches(someBPRequestVO))
.thenReturn(whatYouWant);
Of course, it requires that you write the argument matcher!
当然,它需要你编写参数匹配器!
Note that there is a builtin matcher which can do what you want:
请注意,有一个内置匹配器可以执行您想要的操作:
when(mockBPService.getProduct(eq(someBPRequestVO))).thenReturn(whatYouWant);
This matcher of course requires that your BPRequestVO
class implements equals()
(and hashCode()
too)!
这个匹配器当然需要你的BPRequestVO
类实现equals()
(并且hashCode()
也)!
回答by Victor Godoy
Instead of creating a equals method in your BPRequestVO class you can create a mock argument with "any(YourObject.class)" like this:
您可以使用“any(YourObject.class)”创建一个模拟参数,而不是在您的 BPRequestVO 类中创建一个 equals 方法,如下所示:
when(mockBPService.getProduct(any(BPRequestVO.class))).thenReturn(invalidServiceResponse);