美文网首页
Spring Boot测试

Spring Boot测试

作者: 自负的鱼 | 来源:发表于2018-10-22 14:42 被阅读13次

    Spring Boot测试

    Spring 提供的了一个test框架,用于系统的集成测试。在Spring Boot中,你可以通过spring-boot-starter-test 来启动测试框架。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    

    Junit测试

    进行简单单元测试而不需要Spring Boot特性,可以直接使用Junit编写测试单元。

    @BeforeClass和@AfterClass在类被实例化前(构造方法执行前)就被调用了,而且只执行一次,通常用来初始化和关闭资源。

    @Before和@After和在每个@Test执行前后都会被执行一次。

    @Test标记一个方法为测试方法单元,被@Ignore标记的测试方法不会被执行。

    JUnit4为了保证每个测试方法都是单元测试,是独立的互不影响。所以每个测试方法执行前都会重新实例化测试类。

    Spring Boot测试

    当测试中需要使用Spring Boot功能时,可以使用@SpringBootTest注解,装配Spring上下文。
    当作为普通Spring单元测试时,可以使用@ContextConfiguration,装配Spring 上下文。
    基于Spring 的Junit测试单元需要使用@RunWith(SpringJUnit4ClassRunner.class)注解,该注解能够让Junit运行在Spring测试环境中,得到Spring上下文支持。在4.3版本中提供了等同于SpringJUnit4ClassRunner.class的简写类SpringRunner.class。

    Spring Boot测试单元启动流程如下:

    • 如果未指定classes 参数或者指定的classes参数不是启动main函数入口SpringBootTest(classes = SpringTestAutoConfig.class) ,则会自动从当前测试类包一层一层向上检索,直到找到@SpringBootApplication或@SpringBootConfiguration注释类为止。以此来启动Spring Boot应用,并装载Spring上下文。
    • 如果未检索到Spring Boot启动主配置类,则会抛出异常:java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=…) with your test
    • 如果制定的classes为普通Configer配置类,则会以此配置初始化Spring 上下文,而不会加载其他Bean到Spring 容器。可以在Junit测试单元中使用这些类。
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = {YourApplication.class})
    public class BeanInjectTest {
        
        // ...
        
    }
    

    Spring MVC 测试

    如果要对Spring MVC 测试,可以使用@WebMvcTest 注解,可以在不需要完整启动HTTP服务器就可以快速测试MVC控制器。
    使用@WebMvcTest注解时需要注意,只有部分bean会被加载到Spring 上下文中,分别是:

    • @Controller
    • @ControllerAdvice
    • @JsonComponent
    • Filter
    • WebMvcConfigurer
    • HandlerMethodArgumentResolver

    其他常规的@Component @Bean @Service注解的Bean并不会加载到Spring测试环境。如果要使用这些类,需要使用mock打桩的方式。

    import static org.mockito.BDDMockito.*;
    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
    import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
        
    @RunWith(SpringRunner.class)
    @WebMvcTest(HelloController.class)
    public class HelloControllerTest {
        
        @Autowired
        private MockMvc mvc;
        
        @MockBean
        private HelloService helloService;
        
        @Test
        public void testSayHi() throws Exception {
            // 模拟 HelloService.sayHi() 调用, 返回 "=== Hi ==="
            when(helloService.sayHi()).thenReturn("=== Hi ===");
            mvc.perform(get("/hello/sayHi"))
                    .andExpect(status().isOk())
                    .andDo(print());
        }
        
    }
    

    Spring Boot Web测试

    开启Spring Http服务对Web应用测试,可以使用注解@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)注解开启一个随机的可用端口。Spring Boot针对REST接口调用提供了TestRestTemplate模版。他可以解析链接服务器的接口地址。

    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
    public class ApplicationTest {
        
        @Autowired
        private TestRestTemplate restTemplate;
        
        @Test
        public void testSayHello() {
            Map<String, Object> result = restTemplate.getForObject("/hello/sayHello", Map.class);
            System.out.println(result.get("message"));
        }
        
    }
    

    Spring Data JPA测试

    对Spring Data JPA进行测试可以使用@DataJpaTest注解。@DataJpaTest使用的是内存数据库进行测试,你无需配置和启用真实的数据。在pom配置文件中添加依赖即可。

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>
    

    @DataJpaTest注解只会扫描@Entity 的Bean 和装配 Spring Data JPA 存储库,其他常规@Service @Component @Repository 注解的Bean不会加载到Spring 上下文中。

    @RunWith(SpringRunner.class)
    @DataJpaTest
    public class UserRepositoryInMemoryTest {
        
        @Autowired
        private UserRepository userRepository;
        
        @Test
        public void testSave() {
            User user = new User();
            user.setName("fanlychie");
            userRepository.save(user);
            System.out.println("====================================");
            System.out.println(userRepository.findAll());
            System.out.println("====================================");
        }
        
    }
    
    @Entity(name = "User")
    public class User {
        
        @Id
        @GeneratedValue(generator = "uuidGenerator")
        @GenericGenerator(name = "uuidGenerator", strategy = "uuid")
        private String id;
        
        private String name;
        
        // getters and setters
        
    }
    
    public interface UserRepository extends JpaRepository<User, String> {
        
    }
    

    真实数据库测试

    如果需要使用真实的数据库作为测试,需要添加注解@AutoConfigureTestDatabase(replace = Replace.NONE),通知Spring不要替换原有应用的默认数据库。

    @RunWith(SpringRunner.class)
    @DataJpaTest
    @AutoConfigureTestDatabase(replace = Replace.NONE)
    public class UserRepositoryMySQLTest {
        
        @Autowired
        private UserRepository userRepository;
        
        @Test
        public void testSave() {
            User user = new User();
            user.setName("fanlychie");
            userRepository.save(user);
            System.out.println("====================================");
            System.out.println(userRepository.findAll());
            System.out.println("====================================");
        }
        
    }
    

    事务控制

    默认情况下,在每个jpa测试执行完成时,都会执行事务回滚。从而防止测试数据污染数据库,如果不希望回滚可以在测试方法上添加注解@Rollback(false)。也可以在方法或者类上添加@Transactional作为全局的事务控制。

    @RunWith(SpringRunner.class)
    @DataJpaTest
    @AutoConfigureTestDatabase(replace = Replace.NONE)
    public class UserRepositoryMySQLTest {
        
        @Autowired
        private UserRepository userRepository;
        
        @Test
        @Transactional(readOnly = true)
        public void testSelect() {
            System.out.println("====================================");
            System.out.println(userRepository.findAll());
            System.out.println("====================================");
        }
        
    }
    

    相关文章

      网友评论

          本文标题:Spring Boot测试

          本文链接:https://www.haomeiwen.com/subject/fslgzftx.html