Spring Boot Mockito (三)

Spring Boot Mockito (三)

这篇文章主要是讲解Spring boot 与 Mockito 集成测试。

前期项目配置及依赖可以查看

Spring Boot Mockito (二) - @DataJpaTest
Spring Boot Mockito (一) - @WebMvcTest

java 复制代码
@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

java 复制代码
package pr.iceworld.fernando.springbootmockito.bootstrap;

// ...

@Component
@RequiredArgsConstructor
public class InitData implements CommandLineRunner {
	// ...
}

增加注解@AutoConfigureMockMvc 顾名思义 - 自动化配置 mockMvc, 如以下部分

java 复制代码
/**
 * 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 {
	// ...
}
java 复制代码
@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层,@DataJpaTest用于测试持久层。
@DataJdbcTest - 与 @DataJpaTest功能类似

相关源码已上传到github

相关推荐
IT_陈寒1 小时前
Redis持久化这个坑,我爬了一整天才出来
前端·人工智能·后端
无风听海1 小时前
多租户系统中的 OIDC:Discovery 端点与联合登录的深度实践
后端·python·flask
小小前端仔LC1 小时前
Node.js + LangChain + React:搭建个人知识库(六)- “吃什么”项目实战:从700+菜谱入库到Taro H5端JSON渲染
前端·后端
程序员黑豆2 小时前
AI全栈开发之Java:怎么配置Java环境变量
前端·后端·ai编程
苍何2 小时前
一手实测 Claude Fable 5,手搓了个 Obsidian 的 Codex 插件
后端
逍遥德3 小时前
MQTT教程详解-05.SpringBoot集成mqtt client 性能分析
java·spring boot·spring·mt
点燃大海3 小时前
SpringAI构建智能体
java·spring boot·spring·springai智能体
xier_ran3 小时前
【infra之路】02_RadixAttention与KV_Cache管理
java·spring boot·spring
swipe3 小时前
做多轮对话 Agent,为什么我建议把短期记忆放到 Redis
后端·面试·llm
码客日记3 小时前
Spring Boot 配置文件敏感信息加密(Jasypt 企业级完整方案)
java·spring boot·git