spring boot下进行单元测试
为了提高自己的代码质量,减少低级错误,降低代码验证的成本,特地学习在spring boot下的junit4及spring test的单元测试方法。
环境配置
spring boot中只需要加入以下maven配置即可开始使用junit4及spring test。
maven配置如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
常用注解
@Test
标记在测试方法上。
@RunWith
是junit提供的运行平台扩展接口,在spring boot中,如果想用spring环境,需要使用@RunWith(SpringRunner.class)
@ContextConfigration
用来指定spring的基础配置,可以是xml文件,也可以是java文件。
@SpringBootTest
是spring boot提供的注解,他会自动寻找项目下的springboot启动配置项,不用再自己配置。
@Transactional
注解能够使测试方法中所有事务操作在测试操作完成后进行回滚,避免对环境造成垃圾数据。
@Before
,@After
注解的方法可以在真实的测试方法执行前后执行,与spring mvc的拦截器类似。注意是每一个@Test
方法前后都会执行。
@BeforeClass
,@AfterClass
注解的方法在测试类初始化时及测试类中所有测试方法执行完毕后执行,与@Before
,@After
有区别。
@MockBean||@SpyBean
开发测试环境可能会缺失一些功能,需要进行mock数据。比如依赖的接口没有测试环境,这时候测试的方法中依赖这个接口,就可以mock这个接口的数据。@MockBean和@SpyBean都可以进行数据mock。
@MockBean的使用方法
@Service
@Slf4j
public class TestServiceDefaultImpl implements TestService {
@Override
public String test(String arg1, int arg2) {
return arg1 + arg2;
}
@Override
public String testSay(String arg1, int arg2) {
return "testSay" + arg1 + arg2;
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestControllerTest {
@MockBean
private TestService testService;
@Before
public void before() {
Mockito.when(testService.test("1", 2)).thenReturn("mockBean生效啦");
}
@Test
public void testService() {
System.out.println("test方法返回:"+testService.test("1", 2));
Assert.assertEquals(testService.testSay("1", 2),"testSay12");
}
}
测试结果为:
test方法返回:null
org.junit.ComparisonFailure:
Expected :mockBean生效啦
Actual :testSay12
可以看到已经修改了service的原始方法,但是test方法返回的是null, @MockBean中的方法默认全部返回null,只有专门配置的方法会返回你想要的结果。
@SpyBean的使用方法
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestControllerTest {
@SpyBean
private TestService testService;
@Before
public void before() {
Mockito.doReturn("spybean生肖啦").when(testService).testSay("1", 2);
}
@Test
public void testService() {
System.out.println("test方法返回:"+testService.test("1", 2));
Assert.assertEquals(testService.testSay("1", 2),"testSay12");
}
}
返回结果:
test方法返回:12
org.junit.ComparisonFailure:
Expected :spybean生肖啦
Actual :testSay12
@SpyBean里所有的方法执行原有逻辑,但是可以指定方法返回自己想要的东西。一般情况下,@SpyBean更好用。
MockMVC
controller的单元测试可以使用MockMVC,不在需要自己启动项目,再去使用浏览器或者postman调用。
代码例子:
@RestController
@RequestMapping("/")
public class TestController {
@Autowired
private TestService testService;
@GetMapping("/test")
@TestAnno(age = "15",name = "www")
public String test(String arg1, int arg2) {
return testService.test(arg1, arg2);
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestControllerTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Before
public void before() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void testTest() throws Exception {
MvcResult result = mockMvc.perform(get("/test/?arg1=1&arg2=2")).andExpect(status().isOk()).andReturn();
Assert.assertEquals(result.getResponse().getContentAsString(), "12");
}
}
测试通过,这样可以连带拦截器一起测试。