赞
踩
idea中一般使用JUnit进行单元测试
我们可以在idea的test文件夹下的XXXXApplicationTests内进行单元测试:
可以在@Test标注的方法上写测试代码:
- @SpringBootTest
- class C0101ApplicationTests {
-
- @Test
- fun contextLoads() {
- println("Hello World")
- }
-
- }
我们也可以写多个测试方法:
- @SpringBootTest
- class C0101ApplicationTests {
-
- @Test
- fun test1() {
- println("test1")
- }
-
- @Test
- fun test2() {
- println("test2")
- }
-
- }
我们也可以在测试类内使用@Autowired注解,如我们可以自动注入写好的服务:
- @Autowired
- lateinit var testService: TestService
我们来举个例子,先创建一个服务:
- package com.example.c0101.service
-
- import org.springframework.stereotype.Service
-
- @Service
- class TestService {
- fun check(username: String, password: String): Boolean{
- return username == "admin" && password == "123456"
- }
- }
然后在测试类内使用Autowired自动注入服务,并进行测试:
- package com.example.c0101
-
- import com.example.c0101.service.TestService
- import org.junit.jupiter.api.Test
- import org.springframework.beans.factory.annotation.Autowired
- import org.springframework.boot.test.context.SpringBootTest
-
- @SpringBootTest
- class C0101ApplicationTests {
-
- @Autowired
- lateinit var testService: TestService
-
- @Test
- fun test() {
- println(testService.check("111", "123"))
- println(testService.check("admin", "123456"))
- }
-
- }
控制台输出:
- ...
- false
- true
- ...
我们可以用以下注解实现测前准备和测后收尾:
另外,@BeforeAll和@AfterAll标注的方法需要为静态,在kotlin中需要放在companion object的代码块下,并用@JvmStatic注解标注
以下代码展示了这些注解的用法:
- package com.example.c0101
-
- import com.example.c0101.service.TestService
- import org.junit.jupiter.api.AfterAll
- import org.junit.jupiter.api.AfterEach
- import org.junit.jupiter.api.BeforeAll
- import org.junit.jupiter.api.BeforeEach
- import org.junit.jupiter.api.Test
- import org.junit.jupiter.api.TestInfo
- import org.springframework.beans.factory.annotation.Autowired
- import org.springframework.boot.test.context.SpringBootTest
-
- @SpringBootTest
- class C0101ApplicationTests {
-
- @BeforeEach
- fun beforeEach(info: TestInfo){
- println("即将进入测试方法:${info.testMethod.get()}")
- }
-
- @AfterEach
- fun afterEach(info: TestInfo){
- println("已经离开测试方法:${info.testMethod.get()}")
- }
-
- companion object {
- @JvmStatic
- @BeforeAll
- fun beforeAll(){
- println("即将进入测试")
- }
-
- @JvmStatic
- @AfterAll
- fun afterAll(){
- println("测试已完成")
- }
- }
-
- @Test
- fun test() {
- println("Hello World")
- }
-
- }
控制台输出:
- ...
- 即将进入测试
- ...
- 即将进入测试方法:public void com.example.c0101.C0101ApplicationTests.test()
- Hello World
- 已经离开测试方法:public void com.example.c0101.C0101ApplicationTests.test()
- 测试已完成
- ...
要想设置测试用例,需要使用@ParameterizedTest注解,该注解可以传入name参数,可以为测试方法起别名。另外,可以用@ValueSource注解设置参数源:
- @ParameterizedTest
- @ValueSource(ints = [1, 2, 3, 4, 5])
- fun test(num: Int) {
- println("$num")
- }
注意,被@ParameterizedTest注解标注的测试方法就不需要用@Test注解标注了
JUnit会将所有的测试用例都测试一遍,因此这个测试方法会被执行5次:
- ...
- 1
- 2
- 3
- 4
- 5
- ...
我们也可以用@MethodSource注解设置测试用例,它将会把一个静态方法的返回值作为测试用例:
- companion object{
- @JvmStatic
- fun getInt(): Stream<Int>{
- return Stream.of(1, 2, 3, 4, 5)
- }
- }
-
- @ParameterizedTest
- @MethodSource("getInt")
- fun test(num: Int) {
- println("$num")
- }
注意:这里面的Stream是java.util.stream下的Stream类
使用这种方法,我们就可以传入多个参数了:
- companion object{
- @JvmStatic
- fun getProducts(): Stream<Arguments>{
- return Stream.of(
- Arguments.of("鼠标", 49.9),
- Arguments.of("键盘", 59.9)
- )
- }
- }
-
- @ParameterizedTest
- @MethodSource("getProducts")
- fun test(name: String, price: Double) {
- println("$name 卖 $price 元")
- }
输出:
- ...
- 鼠标 卖 49.9 元
- 键盘 卖 59.9 元
- ...
测试人员可以断言一件事是真的,如果这件事不是真的,则测试失败
JUnit提供了Assertions类,用于进行断言:
- @Test
- fun test() {
- Assertions.assertTrue(1 > 2)
- }
这段代码断言了1>2是真的,如果不是真的(当然不是真的),则测试失败:
还记得之前的测试服务的代码吗,这个服务在传入用户名为admin且密码为123456后应该返回true,如果返回的不是true,说明这个服务写错了;同理,如果传入的用户名不是admin或密码不是123456,则应该返回false,如果返回的不是false,同样说明这个服务写错了。我们可以用断言来测试这个功能:
- @Autowired
- lateinit var testService: TestService
-
- @Test
- fun test() {
- Assertions.assertTrue(testService.check("admin", "123456"))
- Assertions.assertTrue(!testService.check("aaa", "123"))
- }
可以看到,测试通过,说明check没有写错
如果要测试controller等需要使用Servlet对象(例如HttpServletRequest)的方法,就需要模拟Servlet对象,我们可以在测试类自动注入以下对象模拟:
- @Autowired
- lateinit var mockHttpServletRequest: MockHttpServletRequest
- @Autowired
- lateinit var mockHttpServletResponse: MockHttpServletResponse
- @Autowired
- lateinit var mockHttpSession: MockHttpSession
这些代码在idea里可能会报错,不过没有关系
另外,在测试contoller时,同样需要@Autowired:
- @Autowired
- lateinit var controller: TestController
我们来举个模拟Servlet的例子:
先创建一个controller:
- package com.example.c0101.controller
-
- import jakarta.servlet.http.HttpServletRequest
- import jakarta.servlet.http.HttpServletResponse
- import jakarta.servlet.http.HttpSession
- import org.springframework.web.bind.annotation.RequestMapping
- import org.springframework.web.bind.annotation.RestController
-
- @RestController
- class TestController {
-
- @RequestMapping
- fun index(request: HttpServletRequest, response: HttpServletResponse, session: HttpSession): String{
- response.status = 404
- return "Hello World"
- }
-
- }
当访问主页时,会设置状态码为404,并返回Hello World
接下来编写测试类:
- package com.example.c0101
-
- import com.example.c0101.controller.TestController
- import com.example.c0101.service.TestService
- import org.junit.jupiter.api.Assertions
- import org.junit.jupiter.api.Test
- import org.springframework.beans.factory.annotation.Autowired
- import org.springframework.boot.test.context.SpringBootTest
- import org.springframework.mock.web.MockHttpServletRequest
- import org.springframework.mock.web.MockHttpServletResponse
- import org.springframework.mock.web.MockHttpSession
-
- @SpringBootTest
- class C0101ApplicationTests {
-
- @Autowired
- lateinit var controller: TestController
-
- @Autowired
- lateinit var mockHttpServletRequest: MockHttpServletRequest
- @Autowired
- lateinit var mockHttpServletResponse: MockHttpServletResponse
- @Autowired
- lateinit var mockHttpSession: MockHttpSession
-
- @Test
- fun test() {
- val res = controller.index(mockHttpServletRequest, mockHttpServletResponse, mockHttpSession)
- Assertions.assertTrue(mockHttpServletResponse.status == 404)
- println(res)
- }
-
- }
测试类中,我们断言了状态码一定是404,并输出了返回结果
控制台输出如下:
- ...
- Hello World
- ...
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。