Issue
If we have mocks in the MvcMock
test on rest endpoint, can we call it as integration test
? Definitely, I can say TestRestTemplate
test is integration test
as there is no mocking when I test the endpoint.
MvcMock test
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
internal class CreateProductRestControllerMvcTest {
@Autowired
private lateinit var mockMvc: MockMvc
@Autowired
private lateinit var objectMapper: ObjectMapper
@MockkBean
private lateinit var createProductService: CreateProductService
@ParameterizedTest
@ArgumentsSource(ValidCreateProductRequests::class)
internal fun `POST a new Product, GIVEN without any exception, THEN return Product id and status 201`(request: CreateProductRequest) {
// Given
every { createProductService.invoke(request.toCommand()) } returns ProductId(1L)
// When, Then
this.mockMvc.post(REST_PRODUCTS) {
contentType = APPLICATION_JSON
content = objectMapper.writeValueAsString(request)
}
.andExpect {
status { isCreated() }
content { json((objectMapper.writeValueAsString(1L))) }
}
}
}
TestRestTemplate Test
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = [Application::class])
@ActiveProfiles("test")
@Testcontainers
@FlywayTest
@ExtendWith(FlywayTestExtension::class)
class CreateProductRestControllerIntegrationTest {
@Autowired
private lateinit var restTemplate: TestRestTemplate
private lateinit var headers: HttpHeaders
@BeforeEach
internal fun setUp() {
headers = HttpHeaders()
headers.contentType = MediaType.APPLICATION_JSON
}
@FlywayTest
@ParameterizedTest
@ArgumentsSource(ValidJsonRequestBodies::class)
internal fun `POST new Product, GIVEN valid request, THEN returns 201`(json: String) {
// Given
val request: HttpEntity<String> = HttpEntity(json, headers)
// When
val result = restTemplate.postForEntity(REST_PRODUCTS, request, String::class.java);
// Then
assertNotNull(result.body)
assertEquals(HttpStatus.CREATED, result.statusCode)
}
}
Solution
In my opinion, calling it an "integration test" is not completely fair. By mocking the Service you are basically testing your Controller and testing the capability of serializing and deserializing JSON, which is a completely valid test.
In Spring world you might find these being called "slice tests" on which the point of the test is to check a given layer of your application instead of a fully-fledged integration test. More information about them in:
- https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-tests
- https://www.baeldung.com/spring-tests#5-using-test-slices
- https://dzone.com/articles/spring-boot-web-slice-test
Answered By - João Dias