JUnit:求求你了,别再用 main 方法测试了,好吗?(2)

简介: JUnit:求求你了,别再用 main 方法测试了,好吗?

03、瞻前顾后


在一个测试用例中,可能要对多个方法进行测试。在测试之前呢,需要准备一些条件,比如说创建对象;在测试完成后呢,需要把这些对象销毁掉以释放资源。如果在多个测试方法中重复这些样板代码又会显得非常啰嗦。


这时候,该怎么办呢?


我为你提供了 setUp() 和 tearDown(),作为一个文化人,我称之为“瞻前顾后”。来看要测试的代码。


public class Calculator {
    public int sub(int a, int b) {
        return a - b;
    }
    public int add(int a, int b) {
        return a + b;
    }
}

新建测试用例的时候记得勾选setUp 和 tearDown。




生成后的代码如下所示。


class CalculatorTest {
    Calculator calculator;
    @BeforeEach
    void setUp() {
        calculator = new Calculator();
    }
    @AfterEach
    void tearDown() {
        calculator = null;
    }
    @Test
    void sub() {
        assertEquals(0,calculator.sub(1,1));
    }
    @Test
    void add() {
        assertEquals(2,calculator.add(1,1));
    }
}


@BeforeEach 的 setUp() 方法会在运行每个 @Test 方法之前运行;@AfterEach 的 tearDown() 方法会在运行每个 @Test 方法之后运行。


与之对应的还有 @BeforeAll 和 @AfterAll,与 @BeforeEach 和 @AfterEach 不同的是,All 通常用来初始化和销毁静态变量。


public class DatabaseTest {

   static Database db;


   @BeforeAll

   public static void init() {

       db = createDb(...);

   }

 

   @AfterAll

   public static void drop() {

       ...

   }

}



03、异常测试


对于 Java 程序来说,异常处理也非常的重要。对于可能抛出的异常进行测试,本身也是测试的一个重要环节。


还拿之前的 Factorial 类来进行说明。在 fact() 方法的一开始,对参数 n 进行了校验,如果小于 0,则抛出 IllegalArgumentException 异常。


public class Factorial {

   public static long fact(long n) {

       if (n < 0) {

           throw new IllegalArgumentException("参数不能小于 0");

       }

       long r = 1;

       for (long i = 1; i <= n; i++) {

           r = r * i;

       }

       return r;

   }

}



在 FactorialTest 中追加一个测试方法 factIllegalArgument()。


@Test

void factIllegalArgument() {

   assertThrows(IllegalArgumentException.class, new Executable() {

       @Override

       public void execute() throws Throwable {

           Factorial.fact(-2);

       }

   });

}



我为你提供了一个 assertThrows() 的方法,第一个参数是异常的类型,第二个参数 Executable,可以封装产生异常的代码。如果觉得匿名内部类写起来比较复杂的话,可以使用 Lambda 表达式。


@Test

void factIllegalArgumentLambda() {

   assertThrows(IllegalArgumentException.class, () -> {

       Factorial.fact(-2);

   });

}



04、忽略测试


有时候,由于某些原因,某些方法产生了 bug,需要一段时间去修复,在修复之前,该方法对应的测试用例一直是以失败告终的,为了避免这种情况,我为你提供了 @Disabled 注解。


class DisabledTestsDemo {
    @Disabled("该测试用例不再执行,直到编号为 43 的 bug 修复掉")
    @Test
    void testWillBeSkipped() {
    }
    @Test
    void testWillBeExecuted() {
    }
}



@Disabled 注解也可以不需要说明,但我建议你还是提供一下,简单地说明一下为什么这个测试方法要忽略。在上例中,如果团队的其他成员看到说明就会明白,当编号 43 的 bug 修复后,该测试方法会重新启用的。即便是为了提醒自己,也很有必要,因为时间长了你可能自己就忘了,当初是为什么要忽略这个测试方法的。


05、条件测试


有时候,你可能需要在某些条件下运行测试方法,有些条件下不运行测试方法。针对这场使用场景,我为你提供了条件测试。


1)不同的操作系统,可能需要不同的测试用例,比如说 Linux 和 Windows 的路径名是不一样的,通过 @EnabledOnOs 注解就可以针对不同的操作系统启用不同的测试用例。


@Test
@EnabledOnOs(MAC)
void onlyOnMacOs() {
    // ...
}
@TestOnMac
void testOnMac() {
    // ...
}
@Test
@EnabledOnOs({ LINUX, MAC })
void onLinuxOrMac() {
    // ...
}
@Test
@DisabledOnOs(WINDOWS)
void notOnWindows() {
    // ...
}


2)不同的 Java 运行环境,可能也需要不同的测试用例。@EnabledOnJre 和 @EnabledForJreRange 注解就可以满足这个需求。


@Test
@EnabledOnJre(JAVA_8)
void onlyOnJava8() {
    // ...
}
@Test
@EnabledOnJre({ JAVA_9, JAVA_10 })
void onJava9Or10() {
    // ...
}
@Test
@EnabledForJreRange(min = JAVA_9, max = JAVA_11)
void fromJava9to11() {
    // ...
}



06、尾声


最后,给你说三句心里话吧。在编写单元测试的时候,你最好这样做:


1)单元测试的代码本身必须非常名单明了,能一下看明白,决不能再为测试代码编写测试代码。


2)每个单元测试应该互相独立,不依赖运行时的顺序。


3)测试时要特别注意边界条件,比如说 0,null,空字符串"" 等情况。


希望我能尽早的替你发现代码中的 bug,毕竟越早的发现,造成的损失就会越小。see you!


推荐阅读:


鹅厂大佬掏心掏肺的分享:我的编程能力从什么时候开始突飞猛进?


Github 疯传!史上最强!BAT 大佬「LeetCode刷题手册」电子书开放下载了!


如果觉得有帮助的话,请不要吝啬一键三连哦,我知道,你们都是有素质的 CSDN 好公民,2021 年,让我们一起加油!


相关文章
|
2月前
|
测试技术 开发者 Python
Python单元测试入门:3个核心断言方法,帮你快速定位代码bug
本文介绍Python单元测试基础,详解`unittest`框架中的三大核心断言方法:`assertEqual`验证值相等,`assertTrue`和`assertFalse`判断条件真假。通过实例演示其用法,帮助开发者自动化检测代码逻辑,提升测试效率与可靠性。
314 1
|
5月前
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
618 0
|
1月前
|
Java 测试技术 数据库连接
【SpringBoot(四)】还不懂文件上传?JUnit使用?本文带你了解SpringBoot的文件上传、异常处理、组件注入等知识!并且带你领悟JUnit单元测试的使用!
Spring专栏第四章,本文带你上手 SpringBoot 的文件上传、异常处理、组件注入等功能 并且为你演示Junit5的基础上手体验
813 2
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
如何让AI更“聪明”?VLM模型的优化策略与测试方法全解析​
本文系统解析视觉语言模型(VLM)的核心机制、推理优化、评测方法与挑战。涵盖多模态对齐、KV Cache优化、性能测试及主流基准,助你全面掌握VLM技术前沿。建议点赞收藏,深入学习。
617 8
|
5月前
|
测试技术
软考软件评测师——可靠性测试测试方法
软件可靠性是指软件在规定条件和时间内完成预定功能的能力,受运行环境、软件规模、内部结构、开发方法及可靠性投入等因素影响。失效概率指软件运行中出现失效的可能性,可靠度为不发生失效的概率,平均无失效时间(MTTF)体现软件可靠程度。案例分析显示,嵌入式软件需满足高可靠性要求,如机载软件的可靠度需达99.99%以上,通过定量指标评估其是否达标。
|
5月前
|
消息中间件 缓存 监控
性能测试怎么做?方法、流程与核心要点解析
本文系统阐述了性能测试的核心方法论、实施流程、问题定位优化及报告编写规范。涵盖五大测试类型(负载验证、极限压力、基准比对、持续稳定性、弹性扩展)与七项关键指标,详解各阶段任务如需求分析、场景设计和环境搭建,并提供常见瓶颈识别与优化实战案例。最后规范测试报告内容框架与数据可视化建议,为企业级实践提出建立基线库、自动化回归和全链路压测体系等建议,助力高效开展性能测试工作。
|
9月前
|
编解码 缓存 Prometheus
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
本期内容为「ximagine」频道《显示器测试流程》的规范及标准,我们主要使用Calman、DisplayCAL、i1Profiler等软件及CA410、Spyder X、i1Pro 2等设备,是我们目前制作内容数据的重要来源,我们深知所做的仍是比较表面的活儿,和工程师、科研人员相比有着不小的差距,测试并不复杂,但是相当繁琐,收集整理测试无不花费大量时间精力,内容不完善或者有错误的地方,希望大佬指出我们好改进!
627 16
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
|
9月前
|
人工智能 自然语言处理 测试技术
AxBench:斯坦福大学推出评估语言模型控制方法的基准测试框架
AxBench 是由斯坦福大学推出,用于评估语言模型可解释性方法的基准测试框架,支持概念检测和模型转向任务,帮助研究者系统地比较不同控制技术的有效性。
243 5
AxBench:斯坦福大学推出评估语言模型控制方法的基准测试框架
|
8月前
|
Java 测试技术 Android开发
课时148:junit测试工具
课时148介绍了JUnit测试工具的使用,包括定义、配置和编写测试程序。JUnit是流行的用例测试工具,用于确保代码稳定性。
170 0
下一篇
oss云网关配置