使用Mockito时如何在spring测试中清理模拟
我是Mockito的新手,清理时遇到了一些麻烦。
我曾经使用JMock2进行单元测试。据我所知,JMock2将期望和其他模拟信息保存在一个上下文中,该上下文将针对每种测试方法进行重建。因此,每种测试方法都不会受到其他方法的干扰。
使用JMock2时,我对弹簧测试采用了相同的策略,但我发现我的帖子中使用的策略存在潜在的问题:为每种测试方法重建应用程序上下文,因此会减慢整个测试过程。
我注意到有很多文章建议在spring测试中使用Mockito,我想尝试一下。在我在一个测试用例中编写两个测试方法之前,它工作得很好。每种测试方法单独运行时都通过了测试,如果其中一个测试方法一起运行,则会失败。我推测这是因为模拟信息保留在模拟本身中(因为我看不到JMock中的任何上下文对象),并且模拟(和应用程序上下文)在两种测试方法中均共享。
我通过在@Before方法中添加reset()来解决它。我的问题是处理这种情况的最佳实践是什么(reset()的javadoc说如果需要reset()则代码有异味吗?任何想法表示赞赏,在此先感谢。
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {
"file:src/main/webapp/WEB-INF/booking-servlet.xml",
"classpath:test-booking-servlet.xml" })
@WebAppConfiguration
public class PlaceOrderControllerIntegrationTests implements IntegrationTests {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Autowired
private PlaceOrderService placeOrderService;
@Before
public void setup() {
this.mockMvc = webAppContextSetup(this.wac).build();
reset(placeOrderService);// reset mock
}
@Test
public void fowardsToFoodSelectionViewAfterPendingOrderIsPlaced()
throws Exception {
final Address deliveryAddress = new AddressFixture().build();
final String deliveryTime = twoHoursLater();
final PendingOrder pendingOrder = new PendingOrderFixture()
.with(deliveryAddress).at(with(deliveryTime)).build();
when(placeOrderService.placeOrder(deliveryAddress, with(deliveryTime)))
.thenReturn(pendingOrder);
mockMvc.perform(...);
}
@Test
public void returnsToPlaceOrderViewWhenFailsToPlaceOrder() throws Exception {
final Address deliveryAddress = new AddressFixture().build();
final String deliveryTime = twoHoursLater();
final PendingOrder pendingOrder = new PendingOrderFixture()
.with(deliveryAddress).at(with(deliveryTime)).build();
NoAvailableRestaurantException noAvailableRestaurantException = new NoAvailableRestaurantException(
deliveryAddress, with(deliveryTime));
when(placeOrderService.placeOrder(deliveryAddress, with(deliveryTime)))
.thenThrow(noAvailableRestaurantException);
mockMvc.perform(...);
}
回答:
我认为最好在测试方法之后重新设置模拟,因为这意味着确实存在测试期间发生的某些事情需要清除。
如果重置是在测试方法之前完成的,我不确定应该在重置测试之前发生了什么情况?非嘲笑对象呢?是否有原因(也许有)?如果有原因在代码中没有提到它(例如方法名)?等等。
- 背景
使用Spring就像放弃对一个类的单元测试; 使用Spring时,您对测试的控制较少: 隔离 , 实例化 , 生命周期
,可以在单元测试中引用一些looked属性。但是,在许多情况下,Spring提供的库和框架不是那么“ 透明
”,为了进行测试,您可以更好地测试整个组件的实际行为,例如使用Spring MVC,Spring Batch等。
设计这些测试要麻烦得多,因为在许多情况下,这迫使开发人员设计
以认真测试生产代码的行为。由于许多开发人员并不了解有关代码在Spring中如何生活的所有细节,因此尝试使用单元测试来测试类可能会引起很多意外。
但是麻烦仍然存在,测试应该快而小,以向开发人员提供 快速反馈
(例如Infinitest之类的IDE插件非常有用),但是使用Spring进行的测试本质上更慢并且消耗更多的内存。这样一来,它们运行的频率就会降低,甚至完全避免在本地工作站上运行它们,以便以后在CI服务器上发现它们发生故障。
2. Mockito和Spring的生命周期
因此,当为子系统设计 时,您最终会得到很多对象,并且显然还有协作者,这些对象可能被嘲笑了。生命周期由Spring
Runner控制,但Mockito模拟不是。因此,您必须自己管理模拟生命周期。
关于Spring
Batch项目期间的生命周期,我们再次遇到了一些对非模拟的残留影响的问题,因此我们有两种选择,每个测试类只能使用一种测试方法,或者使用肮脏的上下文技巧:@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
。这导致测试速度变慢,内存消耗增加,但这是我们的最佳选择。使用此技巧,您不必重置Mockito模拟。
我对该项目不太了解,但是springockito可以为您提供有关生命周期的一些帮助。该注释子项目似乎更好:它似乎让Spring管理bean的生命周期在Spring容器中,并让测试控制是如何被使用嘲弄。我仍然没有使用此工具的经验,因此可能会有惊喜。
作为免责声明,我非常喜欢Spring,它提供了许多出色的工具来简化其他框架的使用,可以提高生产力,可以帮助设计,但是就像人类发明的每一种工具一样,总会有一个粗糙的边缘(如果不是更多的话…
)。
附带说明一下,有趣的是,这个问题恰好发生在 上下文中,因为JUnit实例化每个测试方法的测试类。如果测试是基于
则该方法可能会有所不同,因为TestNG仅创建测试类的一个实例,无论使用Spring还是什么,其余的模拟字段都是必选的。
旧答案:
我不喜欢在spring的conxtext中使用Mockito模拟。但您是否正在寻找类似的东西:
@After public void reset_mocks() { Mockito.reset(placeOrderService);
}
以上是 使用Mockito时如何在spring测试中清理模拟 的全部内容, 来源链接: utcz.com/qa/432973.html