当前位置:   article > 正文

Springboot教程(五)——单元测试

Springboot教程(五)——单元测试

idea中一般使用JUnit进行单元测试 

基本使用

我们可以在idea的test文件夹下的XXXXApplicationTests内进行单元测试:

可以在@Test标注的方法上写测试代码: 

  1. @SpringBootTest
  2. class C0101ApplicationTests {
  3. @Test
  4. fun contextLoads() {
  5. println("Hello World")
  6. }
  7. }

我们也可以写多个测试方法

  1. @SpringBootTest
  2. class C0101ApplicationTests {
  3. @Test
  4. fun test1() {
  5. println("test1")
  6. }
  7. @Test
  8. fun test2() {
  9. println("test2")
  10. }
  11. }

我们也可以在测试类内使用@Autowired注解,如我们可以自动注入写好的服务:

  1. @Autowired
  2. lateinit var testService: TestService

我们来举个例子,先创建一个服务:

  1. package com.example.c0101.service
  2. import org.springframework.stereotype.Service
  3. @Service
  4. class TestService {
  5. fun check(username: String, password: String): Boolean{
  6. return username == "admin" && password == "123456"
  7. }
  8. }

然后在测试类内使用Autowired自动注入服务,并进行测试:

  1. package com.example.c0101
  2. import com.example.c0101.service.TestService
  3. import org.junit.jupiter.api.Test
  4. import org.springframework.beans.factory.annotation.Autowired
  5. import org.springframework.boot.test.context.SpringBootTest
  6. @SpringBootTest
  7. class C0101ApplicationTests {
  8. @Autowired
  9. lateinit var testService: TestService
  10. @Test
  11. fun test() {
  12. println(testService.check("111", "123"))
  13. println(testService.check("admin", "123456"))
  14. }
  15. }

控制台输出:

  1. ...
  2. false
  3. true
  4. ...

测前准备和测后收尾

我们可以用以下注解实现测前准备和测后收尾:

  • @BeforeEach:在每一个测试方法执行前执行,其标注的方法可以传入一个TestInfo类型的参数,为当前测试信息的对象
  • @AfterEach:在每一个测试方法执行后执行,其标注的方法可以传入一个TestInfo类型的参数,为当前测试信息的对象
  • @BeforeAll:在所有测试方法执行前只执行一次
  • @AfterAll:在所有测试方法执行后只执行一次

另外,@BeforeAll和@AfterAll标注的方法需要为静态,在kotlin中需要放在companion object的代码块下,并用@JvmStatic注解标注


以下代码展示了这些注解的用法:

  1. package com.example.c0101
  2. import com.example.c0101.service.TestService
  3. import org.junit.jupiter.api.AfterAll
  4. import org.junit.jupiter.api.AfterEach
  5. import org.junit.jupiter.api.BeforeAll
  6. import org.junit.jupiter.api.BeforeEach
  7. import org.junit.jupiter.api.Test
  8. import org.junit.jupiter.api.TestInfo
  9. import org.springframework.beans.factory.annotation.Autowired
  10. import org.springframework.boot.test.context.SpringBootTest
  11. @SpringBootTest
  12. class C0101ApplicationTests {
  13. @BeforeEach
  14. fun beforeEach(info: TestInfo){
  15. println("即将进入测试方法:${info.testMethod.get()}")
  16. }
  17. @AfterEach
  18. fun afterEach(info: TestInfo){
  19. println("已经离开测试方法:${info.testMethod.get()}")
  20. }
  21. companion object {
  22. @JvmStatic
  23. @BeforeAll
  24. fun beforeAll(){
  25. println("即将进入测试")
  26. }
  27. @JvmStatic
  28. @AfterAll
  29. fun afterAll(){
  30. println("测试已完成")
  31. }
  32. }
  33. @Test
  34. fun test() {
  35. println("Hello World")
  36. }
  37. }

控制台输出:

  1. ...
  2. 即将进入测试
  3. ...
  4. 即将进入测试方法:public void com.example.c0101.C0101ApplicationTests.test()
  5. Hello World
  6. 已经离开测试方法:public void com.example.c0101.C0101ApplicationTests.test()
  7. 测试已完成
  8. ...

设置测试用例

要想设置测试用例,需要使用@ParameterizedTest注解,该注解可以传入name参数,可以为测试方法起别名。另外,可以用@ValueSource注解设置参数源:

  1. @ParameterizedTest
  2. @ValueSource(ints = [1, 2, 3, 4, 5])
  3. fun test(num: Int) {
  4. println("$num")
  5. }

注意,被@ParameterizedTest注解标注的测试方法就不需要用@Test注解标注了

JUnit会将所有的测试用例都测试一遍,因此这个测试方法会被执行5次:

  1. ...
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. ...

我们也可以用@MethodSource注解设置测试用例,它将会把一个静态方法的返回值作为测试用例:

  1. companion object{
  2. @JvmStatic
  3. fun getInt(): Stream<Int>{
  4. return Stream.of(1, 2, 3, 4, 5)
  5. }
  6. }
  7. @ParameterizedTest
  8. @MethodSource("getInt")
  9. fun test(num: Int) {
  10. println("$num")
  11. }

注意:这里面的Stream是java.util.stream下的Stream类

使用这种方法,我们就可以传入多个参数了:

  1. companion object{
  2. @JvmStatic
  3. fun getProducts(): Stream<Arguments>{
  4. return Stream.of(
  5. Arguments.of("鼠标", 49.9),
  6. Arguments.of("键盘", 59.9)
  7. )
  8. }
  9. }
  10. @ParameterizedTest
  11. @MethodSource("getProducts")
  12. fun test(name: String, price: Double) {
  13. println("$name$price 元")
  14. }

输出:

  1. ...
  2. 鼠标 卖 49.9
  3. 键盘 卖 59.9
  4. ...

断言

测试人员可以断言一件事是真的,如果这件事不是真的,则测试失败

JUnit提供了Assertions类,用于进行断言:

  1. @Test
  2. fun test() {
  3. Assertions.assertTrue(1 > 2)
  4. }

这段代码断言了1>2是真的,如果不是真的(当然不是真的),则测试失败:

idea提示测试失败
标题

断言的应用

还记得之前的测试服务的代码吗,这个服务在传入用户名为admin且密码为123456后应该返回true,如果返回的不是true,说明这个服务写错了;同理,如果传入的用户名不是admin或密码不是123456,则应该返回false,如果返回的不是false,同样说明这个服务写错了。我们可以用断言来测试这个功能:

  1. @Autowired
  2. lateinit var testService: TestService
  3. @Test
  4. fun test() {
  5. Assertions.assertTrue(testService.check("admin", "123456"))
  6. Assertions.assertTrue(!testService.check("aaa", "123"))
  7. }

可以看到,测试通过,说明check没有写错

模拟Servlet对象

如果要测试controller等需要使用Servlet对象(例如HttpServletRequest)的方法,就需要模拟Servlet对象,我们可以在测试类自动注入以下对象模拟:

  1. @Autowired
  2. lateinit var mockHttpServletRequest: MockHttpServletRequest
  3. @Autowired
  4. lateinit var mockHttpServletResponse: MockHttpServletResponse
  5. @Autowired
  6. lateinit var mockHttpSession: MockHttpSession

这些代码在idea里可能会报错,不过没有关系

另外,在测试contoller时,同样需要@Autowired:

  1. @Autowired
  2. lateinit var controller: TestController

我们来举个模拟Servlet的例子:

先创建一个controller:

  1. package com.example.c0101.controller
  2. import jakarta.servlet.http.HttpServletRequest
  3. import jakarta.servlet.http.HttpServletResponse
  4. import jakarta.servlet.http.HttpSession
  5. import org.springframework.web.bind.annotation.RequestMapping
  6. import org.springframework.web.bind.annotation.RestController
  7. @RestController
  8. class TestController {
  9. @RequestMapping
  10. fun index(request: HttpServletRequest, response: HttpServletResponse, session: HttpSession): String{
  11. response.status = 404
  12. return "Hello World"
  13. }
  14. }

当访问主页时,会设置状态码为404,并返回Hello World

接下来编写测试类:

  1. package com.example.c0101
  2. import com.example.c0101.controller.TestController
  3. import com.example.c0101.service.TestService
  4. import org.junit.jupiter.api.Assertions
  5. import org.junit.jupiter.api.Test
  6. import org.springframework.beans.factory.annotation.Autowired
  7. import org.springframework.boot.test.context.SpringBootTest
  8. import org.springframework.mock.web.MockHttpServletRequest
  9. import org.springframework.mock.web.MockHttpServletResponse
  10. import org.springframework.mock.web.MockHttpSession
  11. @SpringBootTest
  12. class C0101ApplicationTests {
  13. @Autowired
  14. lateinit var controller: TestController
  15. @Autowired
  16. lateinit var mockHttpServletRequest: MockHttpServletRequest
  17. @Autowired
  18. lateinit var mockHttpServletResponse: MockHttpServletResponse
  19. @Autowired
  20. lateinit var mockHttpSession: MockHttpSession
  21. @Test
  22. fun test() {
  23. val res = controller.index(mockHttpServletRequest, mockHttpServletResponse, mockHttpSession)
  24. Assertions.assertTrue(mockHttpServletResponse.status == 404)
  25. println(res)
  26. }
  27. }

测试类中,我们断言了状态码一定是404,并输出了返回结果

控制台输出如下:

  1. ...
  2. Hello World
  3. ...

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/220121?site
推荐阅读
相关标签
  

闽ICP备14008679号