Spring Boot测试

2018-10-22  本文已影响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测试单元启动流程如下:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {YourApplication.class})
public class BeanInjectTest {
    
    // ...
    
}

Spring MVC 测试

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

其他常规的@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("====================================");
    }
    
}
上一篇下一篇

猜你喜欢

热点阅读