我试图实现Mockito来测试一个特定的方法,但.thenReturn(…)似乎总是返回一个null对象,而不是我想要的:
切割:
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;
}
}
弹簧配置:
<bean id="testClass" class="com.foo.TestClassFacade">
<property name="bpService" ref="bpService" />
</bean>
<bean id="bpService" class="class.cloud.BPService" />
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);
}
}
系统输出:
1: null
2: ALL
3: Required - TEST
4: null
这里发生的情况是,当我运行测试时,上面用//问题标记的CUT中的行上的serviceResponse对象为null。我的愿望是用我的测试方法中的"invalidServiceResponse"对象填充该对象。从我的System.out.println的输出来看,我的bpRequestVO在内容上似乎与我的someBPRequestVO匹配。
有人能给我看看我在这里缺了什么吗?
谢谢你抽出时间!
不用在BPRequestVO类中创建equals方法,而是可以创建一个带有"any(YourObject.class)"的模拟参数,如下所示:
when(mockBPService.getProduct(any(BPRequestVO.class))).thenReturn(invalidServiceResponse);
与when()
一起使用的BPRequestVO实例与getTestData()
中使用的实例不同
除非覆盖equals()
,否则它们将不匹配。
如果重写equals(),则不需要编写自定义Matcher。请注意Mockito文档中的以下内容:
"自定义参数匹配器会降低测试的可读性。有时,最好为传递给mock的参数实现equals()(Mockito自然会使用equals(()进行参数匹配)。这可以使测试更干净。"
问题出在when()
的使用上。
您提交了对已构建实例的引用;因此,只有当传递给方法的参数是相同的引用时,mocking才会返回您想要的内容。
你想要的是一个论据匹配者;类似于:
when(mockBPService.getProduct(argThatMatches(someBPRequestVO))
.thenReturn(whatYouWant);
当然,它要求您编写参数匹配器!
注意,有一个内置的匹配器可以做你想做的事:
when(mockBPService.getProduct(eq(someBPRequestVO))).thenReturn(whatYouWant);
这个匹配器当然要求BPRequestVO
类实现equals()
(以及hashCode()
)!
我的问题是模拟服务被定义为最终服务。
用于mocking的BPRequestVO对象实例与junit执行时使用的实例不同。
最好的方法是在模拟的同时配置对象的任何实例
when(mockBPService.getProduct(someBPRequestVO)).thenReturn(invalidServiceResponse);
可以使用进行更新
when(mockBPService.getProduct(Mockito.any(BPRequestVO.class))).thenReturn(invalidServiceResponse);
我的问题是传递null,因为方法参数与我设置的when()子句不匹配。
例如
Car car = mock(Car.class)
when(car.start(anyString()).thenReturn("vroom");
assertEquals("vroom", car.start(null));
这将失败。
assertEquals("vroom", car.start("Now"));
这就过去了。
我的问题是自动连接的服务实例/mmockbean在测试时有不同的实例->给定()部分,在执行过程中它有不同的实例。
这是通过在调试模式下运行测试并检查mock存根和执行代码中的每个值来发现的。如果所有参数和模拟实例都相同,那么只有thenReturn()会返回期望值。
在myscenario中,类的模拟实例有多个实现,通过添加@Qualifier("name"),实例在given()和实际执行中变得相同。
在多线程的情况下也可能发生这种情况。mockito在@Test方法返回后重置了模拟对象的处理程序,而某处(另一个线程)仍在使用模拟对象。
对于线程池提供的情况,您可以模拟线程池,在当前线程中执行Runner.run()被证明是有效的。