I have the following class to test a job of my spring application.
This job updates the state of an order object resorting to an external API.
When I just run the class the test is successful but when I run as part of a gradlew task (that run multiple integration tests, including this one) it fails with:
Wanted but not invoked:
client.updateOrder(
"o11111",
<Pending order update integration test$$ lambda$ 3 9 9/ 1 6 3 9 3 4 9 4 3 5>
);
-> at OrderUpdateIntegrationTest.shouldSendPendingOrderUpdatesSubmittedOrders(OrderUpdateIntegrationTest.java:77)
Actually, there were zero interactions with this mock.
Test class:
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = TestConfig.class)
@ExtendWith(value = {SpringExtension.class, MockitoExtension.class})
@ActiveProfiles("integration-test")
@DirtiesContext
public class OrderUpdateIntegrationTest {
private static final String ORDER_ID_1 = "o11111";
private static final String ORDER_ID_2 = "o22222";
static VerificationWithTimeout FIVE_SECOND_TIMEOUT = timeout(SECONDS.toMillis(5));
@Autowired
private TestScheduleConfigurer testScheduleConfigurer;
@MockBean
private OrdersClient client;
@MockBean
private UpdatePendingOrdersTasklet updateOrderAndSendEmail;
@MockBean
private UrlBuilder urlBuilder;
@Mock
private ResponseEntity<Order> mock200HttpResponse;
@Mock
private ResponseEntity<String> mockEmail200HttpResponse;
private Order order11111;
private Order order22222;
private OrderList ordersList = new OrderList();
@Test
public void shouldSendPendingOrderUpdatesSubmittedOrders() throws Exception {
order11111 = buildOrder(ORDER_ID_1);
order22222 = buildOrder(ORDER_ID_2);
ordersList.setItems(Arrays.asList(order11111, order22222));
when(client.getPendingOrdersObject(anyString())).thenReturn(ordersList);
when(client.updateOrder(any(String.class), any(Order.class))).thenReturn(mock200HttpResponse);
when(mock200HttpResponse.getStatusCode()).thenReturn(HttpStatus.OK);
when(updateOrderAndSendEmail.postSendEmail(any(JSONObject.class))).thenReturn(mockEmail200HttpResponse);
when(mockEmail200HttpResponse.getStatusCode()).thenReturn(HttpStatus.OK);
testScheduleConfigurer.triggerPendingOrderUpdateSchedule();
verify(client, FIVE_SECOND_TIMEOUT).updateOrder(eq(ORDER_ID_1), argThat(argument -> argument.getState().equals(OrderState.PROCESSING)));
verify(client, FIVE_SECOND_TIMEOUT).updateOrder(eq(ORDER_ID_2), argThat(argument -> argument.getState().equals(OrderState.PROCESSING)));
verify(urlBuilder, times(2)).buildComponent("emailNotifications");
}
private Order buildOrder(String orderId) {
Order order = new Order();
order.setId(orderId);
order.setSiteId("testSite");
order.setState(OrderState.SUBMITTED);
order.setLastModifiedDate("2019-10-20T01:02:03.004Z");
OrderShippingGroup shippingGroup = new OrderShippingGroup();
OrderAddress emailAddress = new OrderAddress();
emailaddress.setemail("[email protected]");
emailAddress.setFirstName("First Name");
emailAddress.setLastName("Last Name");
shippingGroup.setShippingAddress(emailAddress);
order.setShippingGroups(Arrays.asList(shippingGroup));
return order;
}
}
I think that the problem is, when I just run the test the @MockBean
tag creates a new instance of OrdersClient
to the context, so when a when()
or verify()
method is called, it works as expected but if the integration test is executed as a gradlew task, the job might be using a different instance than the one declared as @MockBean
.
Is there a way to use the same instance for the two scenarios? If this assumption is correct. If not, what is wrong?
Thank you, Pedro.
updateOrder
method was missing multiple mockups so it file with different application configurations.