junit4 Github 仓库地址:junit-team / junit4
junit5 Github 仓库地址:junit-team / junit5
@BeforeClass:
@BeforeClass注解的public void方法将会在所有测试方法执行之前执行。
@BeforeClass注解修饰的方法必须是静态方法。
@BeforeClass public static void setUpBeforeClass() { System.out.println("@BeforeClass修饰的方法会在所有测试方法执行之前执行"); }@AfterClass:
@AfterClass注解的public void方法将会在所有方法执行完毕之后执行。
@AfterClass注解修饰的方法必须是静态方法。
@AfterClass public static void tearDownAfterClass() throws Exception { System.out.println("@AfterClass修饰的方法会在所有方法执行完毕之后执行"); }@After:
@After注解的public void方法将会在每个测试方法执行之后执行一次。
@After注解修饰的方法必须不是静态方法。
@After public void tearDown() throws Exception { System.out.println("@After修饰的方法会在每个测试方法执行之后执行一次"); }@Ignore:
对包含测试类的类或@Test注解方法使用@Ignore注解将使被注解的类或方法不会被当做测试执行。
@Ignore("这个方法很傲娇,不想被测试") @Test public void test() { System.out.println("test..."); }@Test:
@Test注解的public void方法将会被当做测试用例。
注解参数expected:定义测试方法应该抛出的异常,如果测试方法没有抛出异常或者抛出了一个不同的异常,测试失败。
注解参数timeout:如果测试运行时间长于该定义时间,测试失败(单位为毫秒)。
@Test(expected = RuntimeException.class, timeout = 1000) public void test2() { System.out.println("test..."); throw new RuntimeException("我错了。。。"); } @Test(expected = RuntimeException.class) public void test3() { System.out.println("test..."); } @Test(timeout = 1000) public void test4() throws InterruptedException { System.out.println("test..."); Thread.sleep(2000); }通过org.junit.FixMethodOrder可以指定对应的org.junit.runners.MethodSorters排序策略
MethodSorters提供了三种策略:
NAME_ASCENDING(MethodSorter.NAME_ASCENDING): 按照方法名字典顺序JVM(null): 按照JVM返回的顺序DEFAULT(MethodSorter.DEFAULT: 默认,通过查看DEFAULT这个Comparator函数源码可知,按照方法名的hashCode值排序 @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class Junit4Test { }Junit5由来自三个不同子项目的几个不同模块组成。
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
JUnit Platform: Junit Platform是在JVM上启动测试框架的基础,不仅支持Junit自制的测试引擎,其他测试引擎也都可以接入。JUnit Jupiter: JUnit Jupiter提供了JUnit5的新的编程模型,是JUnit5新特性的核心。内部 包含了一个测试引擎,用于在Junit Platform上运行。JUnit Vintage: 由于JUint已经发展多年,为了照顾老的项目,JUnit Vintage提供了兼容JUnit4.x,Junit3.x的测试引擎。Junit5一些常用注解说明,package位置org.junit.jupiter.api。
@Test :表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试@ParameterizedTest :表示方法是参数化测试@RepeatedTest :表示方法可重复执行@TestFactory :测试工厂进行动态测试@DisplayName :为测试类或者测试方法设置展示名称@BeforeEach :表示在每个单元测试之前执行@AfterEach :表示在每个单元测试之后执行@BeforeAll :表示在所有单元测试之前执行@AfterAll :表示在所有单元测试之后执行@Tag :表示单元测试类别,类似于JUnit4中的@Categories@Disabled :表示测试类或测试方法不执行,类似于JUnit4中的@Ignore@Timeout :表示测试方法运行如果超过了指定时间将会返回错误@Nested :嵌套嵌套测试@ExtendWith :为测试类或测试方法提供扩展类引用通过org.junit.jupiter.api.TestMethodOrder可以指定对应的org.junit.jupiter.api.MethodOrderer排序策略
MethodOrderer提供了三种策略:
Alphanumeric:根据测试方法的名称和形式参数列表对它们进行字母数字排序。OrderAnnotation:根据通过注释指定的值对测试方法进行数字排序org.junit.jupiter.api.Order。Random:伪随机地执行测试方法,并支持自定义随机策略的配置。 import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; //@TestMethodOrder(MethodOrderer.Alphanumeric.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) //@TestMethodOrder(MethodOrderer.Random.class) class OrderedTestsDemo { @Test @Order(1) void nullValues() { // perform assertions against null values } @Test @Order(2) void emptyValues() { // perform assertions against empty values } @Test @Order(3) void validValues() { // perform assertions against valid values } }Junit的测试有局限性,无法直接测试启动后Spring环境的功能,借助Spring提供的spring-boot-starter-test依赖,可以便捷的调试Spring容器中Bean的功能。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>@SpringBootTest这个注解所在的文件一定要和注解@SpringBootApplication在同个层级的文件目录下。
@RunWith(SpringRunner.class) @SpringBootTest public class ApplicationTests { }@Transactional:
@Transactional注解修饰的类或方法,可以自动完成事务回滚。
@Rollback:
Spring Boot中使用@Transactional默认回滚事务,而使用@Rollback可以阻止事务自动回滚。
@Rollback(true)默认值是true,表示事务会自动回滚,若是想不回滚事务,将值设置为false即可:@Rollback(false)。
@TestConfiguration:
@TestConfiguration是Spring Boot Test提供的一种工具,用它我们可以在一般的@Configuration之外补充测试专门用的Bean或者自定义的配置。
@TestConfiguration能够:
补充额外的Bean覆盖已存在的Bean@ContextConfiguration:
在 Spring Boot 测试中引入多个配置。
引入配置文件:
@ContextConfiguration(Locations="classpath:applicationContext.xml")引入配置类型:
@ContextConfiguration(classes = SimpleConfiguration.class)junit提供了测试套件,就是可以运行一个测试类使得一个或一些测试类被junit测试运行。
方式:在打包测试类上使用@RunWith标注传递一个参数 Suite.class 。同时,我们还需要另外一个标注 @Suite.SuiteClasses ,来表明这个类是一个打包测试类。
import org.junit.runner.RunWith; import org.junit.runners.Suite; /** * 打包测试 */ @RunWith(Suite.class) @Suite.SuiteClasses({ Junit4Test.class, TestingApplicationTests.class }) public class AllTests { }Mock测试使用的是Mockito框架,在测试的执行过程中使用Mockito的mock模拟底层数据的返回,达到测试web程序的目的。
注入mock测试实例有两种方式。
方式一:注入 web 程序上下文,初始化MockMvc实例。
import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringRunner.class) @SpringBootTest public class MockMvcExampleTests2 { @Autowired private WebApplicationContext webApplicationContext; private MockMvc mvc; @Before public void setUp() throws Exception { mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); } @Test public void exampleTest() throws Exception { MvcResult mvcResult = this.mvc.perform(get("/")) //期望响应状态正常 .andExpect(status().isOk()) //期望响应的信息为:Hello,World! .andExpect(content().string("Hello,World!")) .andReturn(); System.out.println(mvcResult.getResponse().getContentAsString()); } }方式二:在 Spring Boot 测试类上添加注解@AutoConfigureMockMvc。
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class MockMvcExampleTests { @Autowired private MockMvc mvc; @Test public void exampleTest() throws Exception { MvcResult mvcResult = this.mvc.perform(get("/")) //期望响应状态正常 .andExpect(status().isOk()) //期望响应的信息为:Hello,World! .andExpect(content().string("Hello,World!")) .andReturn(); System.out.println(mvcResult.getResponse().getContentAsString()); } }@MockBean主要作用是:使用mock对象代替原来spring的bean,然后模拟底层数据的返回,而不是调用原本真正的实现。
示例:这里接口返回的数据已经不是原本repository查询到的数据,而是mock模拟的对象返回的数据。
import com.example.testing.entity.User; import com.example.testing.repository.UserRepository; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import java.util.ArrayList; import java.util.List; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class MockMvcExampleTests { @Autowired private MockMvc mvc; /** * 使用@MockBean模拟相应对象 */ @MockBean private UserRepository userRepository; @Test public void exampleTest() throws Exception { List<User> users = new ArrayList<>(); User user = new User(); user.setId(1L); user.setUsername("Github"); user.setPassword("123456"); users.add(user); Mockito.when(userRepository.findAll()).thenReturn(users); MvcResult mvcResult = this.mvc.perform(get("/user/query/all")) .andExpect(status().isOk()) .andDo(MockMvcResultHandlers.print()) .andExpect(content().string(mapper.writeValueAsString(users))) .andReturn(); System.out.println(mvcResult.getResponse().getContentAsString()); } }