jUnit的学习笔记

要不要做单元测试的思考

单元测试又称模块测试,是对最小单元的程序模块进行正确性检测。
单元测试本身可以提高代码质量,不过要不要做单元测试,需要从功能的复杂度和功能性质来考虑。
(1)编写的工具类不建议在主程序中出现test的方法,所以可以采用单元测试,这样不会打包到主程序中。
(2)根据功能复杂度考虑单元测试,复杂的功能尽量拆到最小单元,不要让单元测试加重编码负担。
java主要用jUnit单元测试,后面记录下jUnit的使用。

jUnit的使用

maven引入junit包,以下是junit4。

<dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>自己找一个版本</version>
        <scope>test</scope>
</dependency>

junit5换成了org.junit.jupiter包。

<dependency>
     <groupId>org.junit.jupiter</groupId>
     <artifactId>junit-jupiter</artifactId>
     <scope>test</scope>
</dependency>
jUnit的一些注意事项
  • 测试方法必须使用 @Test 修饰。
  • 测试方法必须使用 public void 进行修饰,不能带参数。
  • 使用单元测试会新建一个 test 目录存放测试代码,在生产部署的时候不引入 test 目录下代码。
  • 测试代码的包应该和被测试代码包结构保持一致。
  • 测试单元中的每个方法必须可以独立测试,方法间不能有任何依赖。
  • 测试类一般使用 Test 作为类名的后缀。
  • 测试方法使一般用 test作为方法名的前缀。
注解 junit4
  • @Test:将一个普通方法修饰成一个测试方法。@Test(excepted=xx.class):xx.class表示异常类,表示测试的方法抛出此异常时,认为是正常的测试通过。@Test(timeout = 毫秒数) :测试方法执行时间是否符合预期。
  • @BeforeClass: 会在所有的方法执行前被执行,static 方法 (全局只会执行一次,而且是第一个运行)。
  • @AfterClass:会在所有的方法执行之后进行执行,static 方法 (全局只会执行一次,而且是最后一个运行)。
  • @Before:会在每一个测试方法被运行前执行一次。
  • @After:会在每一个测试方法运行后被执行一次。
  • @Ignore:所修饰的测试方法会被测试运行器忽略。
  • @RunWith:可以更改测试运行器 org.junit.runner.Runner。
注解 junit5

@Test:该注解存在于org.junit.jupiter.api包。
@BeforeEach:在单元测试方法执行前执行,每个单元测试方法都会执行一次。
@BeforeAll:在单元测试方法执行前执行,静态方法,每次运行只执行一次。
@AfterEach:在单元测试方法执行之后执行,每个方法都会执行一次。
@AfterAll:在所有单元测试类方法执行之后执行,静态方法,每次运行只执行一次。
@DisplayName:用来指定单元测试的名称。
@Disabled:设置单元测试无效,跳过执行。
@ExtendWith:可以重复组合扩展。

Assert断言
//junit4
Assert.assertFalse("连接失败!",Objects.isNull(db));
Assert.assertEquals("匹配失败!",2,3);
//junit5
assertEquals(1,2,"匹配失败~");
JUnitCore

测试用例是使用 JUnitCore 类来执行的,每个单元测试类都可以作为测试用例。
JUnitCore 是运行测试的外观类,可通过循环打印错误信息。

public class TestRunner {
    public static void main(String[] args) {
        Result result = JUnitCore.runClasses(TestJunit.class);
        for (Failure failure : result.getFailures()) {
            System.out.println(failure.toString());
        }
        System.out.println(result.wasSuccessful());
    }
}
TestCase

测试样例定义了运行多重测试的固定格式。例如:

public class DBTestCase extends TestCase {
    public void test(){
        int i =this.countTestCases();
        String name=this.getName();
    }
}
TestResult

TestResult收集所有执行测试案例的结果,是收集参数层面的一个实例。它区分失败和错误,失败是可以预料的并且可以通过假设来检查,错误是不可预料的问题比如异常。

public class DBTestResult extends TestResult {
    public synchronized void addError(Test test, Throwable t) {
        super.addError((junit.framework.Test) test, t);
    }
}
TestSuite 测试套件

可以运行很多测试用例。

public static void main(String[] args) {
        //测试套件
        TestSuite suite = new TestSuite(DbTest.class, DBTestCase.class, DBTestResult.class );
        TestResult testResult = new TestResult();
        suite.run(testResult);
        System.out.println("测试数量 = " + testResult.runCount());
    }

测试套件的类

@RunWith(Suite.class)
@Suite.SuiteClasses({ DbTest.class, DemoTest.class })
public class AllTest {
	//此处不写代码,写了也不会执行
}
忽略测试

junit4:@Ignore这个注解可以忽略测试,可放到类上也可以放到方法上。
junit5:@Disabled。

时间测试

junit4:@Test(timeout=1000)给测试方法添加了暂停时间,超时会测试停止,并不通过。
junit5:@TimeOut(1000)。

异常测试

junit4:@Test(expected = XxxxxException.class)为追踪异常的选项,可以测试代码是否它抛出了想要得到的异常。

参数化测试

参数化测试允许开发人员使用不同的值反复运行同一个测试。直接附上官方的代码吧,例子是将预设的参数数据和validate方法进行断言判断是否正确。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.assertEquals;

@RunWith(Parameterized.class)
public class ParameterTest {
    private Integer inputNumber;
    private Boolean expectedResult;

    // Each parameter should be placed as an argument here
    // Every time runner triggers, it will pass the arguments
    // from parameters we defined in primeNumbers() method
    public ParameterTest(Integer inputNumber,
                                  Boolean expectedResult) {
        this.inputNumber = inputNumber;
        this.expectedResult = expectedResult;
    }

    @Parameterized.Parameters
    public static Collection primeNumbers() {
        return Arrays.asList(new Object[][] {
                { 2, true },
                { 6, false },
                { 19, true },
                { 22, false },
                { 23, true }
        });
    }

    // This test will run 4 times since we have 5 parameters defined
    @Test
    public void testPrimeNumberChecker() {
        System.out.println("Parameterized Number is : " + inputNumber);
        assertEquals(expectedResult,
                validate(inputNumber));
    }

    public Boolean validate(final Integer primeNumber) {
        for (int i = 2; i < (primeNumber / 2); i++) {
            if (primeNumber % i == 0) {
                return false;
            }
        }
        return true;
    }
}

jUnit中遇到的问题

1.多线程测试时,jUnit自动退出了?

jUnit执行完主程序会自动结束,就一起将子线程也断掉了。解决这种情况需要用到计数器CountDownLatch。

	@Test
    public void testThread() throws InterruptedException {
        TestClass testClass = new TestClass();
        //同步计数器
        int count = 20;
        CountDownLatch countDownLatch = new CountDownLatch(count);
        for (int i = 1; i <= count; i++) {
            new Thread(() -> {
            	//业务处理
                testClass.write(path, "writeString");
                countDownLatch.countDown();
            }).start();
        }
        countDownLatch.await();
    }
2.测试入库的数据时,执行成功了数据却没有入库?

由于junit不会将数据真是存入数据库,想要真实入库需要自己加commit提交。

3.idea中打包去掉test。

图中图标可去掉test。
去掉test

4.idea如何根据类生成测试类?

光标放到类名上,alt+enter,选择create test,即可在test目录下得到测试类。

5.junit4和junit5的一些区别?

(1)注解不同,用法类似,名称不同。
(2)包不同,旧的单元测试类改成junit5的时候要注意import的内容是否更新。
(3)断言的用法也有变化,用新的传参即可。

6.插件的使用。

在idea中,可以下载插件Squaretest,配置模板。通过alt+insert可以选择Generate Test 创建单元测试类,里面用到了mockito。可以mock很多数据。
依赖如下:

<dependency>
     <groupId>org.junit.jupiter</groupId>
     <artifactId>junit-jupiter</artifactId>
     <scope>test</scope>
</dependency>
<dependency>
     <groupId>org.mockito</groupId>
     <artifactId>mockito-core</artifactId>
     <scope>test</scope>
</dependency>
<dependency>
     <groupId>org.mockito</groupId>
     <artifactId>mockito-inline</artifactId>
     <scope>test</scope>
     </dependency>
<dependency>
     <groupId>org.mockito</groupId>
     <artifactId>mockito-junit-jupiter</artifactId>
     <scope>test</scope>
</dependency>

写几个mock的例子:

//mock Request
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
when(request.getMethod()).thenReturn("post");
//mock 静态方法
MockedStatic<Helper> helper = Mockito.mockStatic(Helper.class);
//返回真实的方法
helper.when(() -> =Helper.getHelper(any())).thenCallRealMethod();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值