Spring Boot Mockito (三)
这篇文章主要是讲解Spring boot 与 Mockito 集成测试。
前期项目配置及依赖可以查看
Spring Boot Mockito (二) - @DataJpaTest
Spring Boot Mockito (一) - @WebMvcTest
@Tag("Integration")
@SpringBootTest
// @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class SpringBootMockitoApplicationTests {
@Autowired
OrderController orderController;
@Autowired
OrderRepository orderRepository;
@Autowired
OrderService orderService;
@Autowired
ObjectMapper objectMapper;
@Autowired
WebApplicationContext wac;
MockMvc mockMvc;
@BeforeEach
void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
@Test
@org.junit.jupiter.api.Order(1)
void test_ListAllOrders() throws Exception {
long count = orderRepository.count();
ResultActions resultActions = mockMvc.perform(get(ORDER_PATH))
.andExpect(status().isOk());
resultActions.andExpect(jsonPath("$.size()").value(count));
//System.out.println(resultActions.andReturn().getResponse().getContentAsString(Charset.forName("UTF-8")));
}
@org.junit.jupiter.api.Order(2)
@Test
void test_GetOrderById() throws Exception {
Order order = orderRepository.findAll().get(0);
ResultActions resultActions = mockMvc.perform(get(ORDER_PATH + "/{id}", order.getId()))
.andExpect(status().isOk());
resultActions.andExpect(jsonPath("$.id").value(order.getId()))
.andExpect(jsonPath("$.name").value(order.getName()))
.andExpect(jsonPath("$.price").value(order.getPrice()));
}
@org.junit.jupiter.api.Order(3)
@Test
void test_GetOrderById_404() throws Exception {
Long orderId = orderRepository.findAll().stream().mapToLong(e -> e.getId()).max().orElse(0) + 10;
ResultActions resultActions = mockMvc.perform(get(ORDER_PATH + "/{id}", orderId))
.andExpect(status().isNotFound());
}
@org.junit.jupiter.api.Order(4)
@Test
void test_UpdateOrderById() throws Exception {
Order order = orderRepository.findAll().get(0);
Order updatedOrder = order;
updatedOrder.setName("Picnic pot");
updatedOrder.setPrice(95.5d);
mockMvc.perform(put(ORDER_PATH + "/{id}", order.getId())
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(updatedOrder)))
.andExpect(status().isNoContent());
order = orderRepository.findById(order.getId()).get();
assertEquals(order.getId(), updatedOrder.getId());
assertEquals(order.getName(), updatedOrder.getName());
assertEquals(order.getPrice(), updatedOrder.getPrice());
}
@org.junit.jupiter.api.Order(5)
@Test
void test_UpdateOrderById_404() throws Exception {
Order order = orderRepository.findAll().get(0);
Long orderId = orderRepository.findAll().stream().mapToLong(e -> e.getId()).max().orElse(0) + 10;
Order updatedOrder = order;
updatedOrder.setId(orderId + 10);
updatedOrder.setName("Picnic pot");
updatedOrder.setPrice(95.5d);
mockMvc.perform(put(ORDER_PATH + "/{id}", updatedOrder.getId())
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(updatedOrder)))
.andExpect(status().isNotFound());
}
@org.junit.jupiter.api.Order(6)
@Test
void test_CreateNewOrder() throws Exception {
Order order = Order.builder()
.name("Picnic pot")
.price(95.5d)
.build();
ResultActions resultActions = mockMvc.perform(post(ORDER_PATH)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(order)))
.andExpect(status().isCreated());
Order createdOrder = objectMapper.readValue(resultActions.andReturn().getResponse().getContentAsString(), Order.class);
order = orderRepository.findById(createdOrder.getId()).get();
assertNotNull(order);
}
@org.junit.jupiter.api.Order(7)
@Test
void test_DeleteOrderById() throws Exception {
Order order = orderRepository.findAll().get(0);
mockMvc.perform(delete(ORDER_PATH + "/{id}", order.getId()))
.andExpect(status().isNoContent());
Optional<Order> existed = orderRepository.findById(order.getId());
assertFalse(existed.isPresent());
}
@org.junit.jupiter.api.Order(8)
@Test
void test_DeleteOrderById_404() throws Exception {
Long orderId = orderRepository.findAll().stream().mapToLong(e -> e.getId()).max().orElse(0) + 10;
mockMvc.perform(delete(ORDER_PATH + "/{id}", orderId))
.andExpect(status().isNotFound());
}
}
@org.junit.jupiter.api.Order
在这里没有起作用是由于已注释了@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
将 InitData
类 移入到了测试文件夹中,SpringBootApplication主类启动不会加载InitData
类
package pr.iceworld.fernando.springbootmockito.bootstrap;
// ...
@Component
@RequiredArgsConstructor
public class InitData implements CommandLineRunner {
// ...
}
增加注解@AutoConfigureMockMvc
顾名思义 - 自动化配置 mockMvc
, 如以下部分
/**
* Annotation that can be applied to a test class to enable and configure
* auto-configuration of {@link MockMvc}.
* ...
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@ImportAutoConfiguration
@PropertyMapping("spring.test.mockmvc")
public @interface AutoConfigureMockMvc {
// ...
}
@Tag("Integration")
@SpringBootTest
// @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@AutoConfigureMockMvc
class SpringBootMockitoApplicationTests {
// ...
// @Autowired
// WebApplicationContext wac;
@Autowired
MockMvc mockMvc;
@BeforeEach
void setUp() {
// mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
// ...
}
@SpringBootTest
- Spring Boot为集成测试提供了@SpringBootTest
注释。此注释创建应用程序上下文并加载完整的应用程序上下文。
@WebMvcTest
- SpringBoot提供@WebMvcTest
注释来测试Spring MVC控制器。基于@WebMvcTest的测试运行得更快,因为它只加载指定的控制器及其依赖项,而不加载整个应用程序。
Spring Boot只实例化web层,而不是整个应用程序上下文。在具有多个控制器的应用程序中,还可以通过使用@WebMvcTest(TestControllerOnly.class)
来仅实例化一个控制器。
@DataJpaTest
- 就像@WebMvcTest
可以测试web层,@DataJpaTes
t用于测试持久层。
@DataJdbcTest
- 与 @DataJpaTest
功能类似
相关源码已上传到github