I used to use JMock2 for unit tests. As far as I know, JMock2 preserves the expectations and other mock information in a context which will be rebuilt for every test method. Therefore every test method is not interfered by the others.
I adopted the same strategy for spring tests when using JMock2, I found a potential problem with the strategies I used in my post: The application context is rebuilt for every test method and therefore slows the whole test procedure.
I noticed many articles recommend using Mockito in spring tests and I would like to have a try. It works well until I write two test method in a test case. Each test method passed when it ran alone, One of them failed if they ran together. I speculated that this is because the mock infomation was preserved in the mock itself('cause I don't see any context object like that in JMock) and the mock(and the application context) is shared in both test methods.
I solved it by adding reset() in @Before method. My question is what is the best practice to handle this situation (The javadoc of reset() says that the code is smell if you need reset())? Any idea is appreciated.
@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(...);
}