java程序员如何编写更好的单元测试的7个技巧

下面是针对"Java程序员如何编写更好的单元测试的7个技巧"的一份攻略。

技巧1:拆分单元测试

单元测试应该足够小,以至于一个单元测试只需要测试一个方法或函数。这样使得测试容易重复、快速执行和简单调试。拆分单元测试也使测试更精确,因为每个单元测试只测试一个输入和输出组合。

示例:

以下是一个简单的 Java 类,将两个整数相加并返回结果:

public class Addition {
    public static int add(int a, int b) {
        return a + b;
    }
}

对于此类,将它拆分成两个单元测试,一个测试方法参数都为正数的情况,另一个测试方法参数一个为正数一个为负数的情况:

@Test
public void testAddition_positiveNumbers() {
    int result = Addition.add(2, 4);
    assertEquals(6, result);
}

@Test
public void testAddition_mixedNumbers() {
    int result = Addition.add(2, -4);
    assertEquals(-2, result);
}

技巧2:引入测试数据工厂

在编写单元测试时,我们需要为每个测试方法提供各种输入,并检查其输出。如果您手动编写每个测试用例,这将非常困难和耗费时间。测试数据工厂是测试单元函数时的好伙伴。它内置于测试库中,其中包含一些基本的测试函数和生成测试数据的工具类。

示例:

以下是一个 Java 类,将两个字符串连接在一起并返回结果:

public class Concatenation {
    public static String concat(String a, String b) {
        return a + " " + b;
    }
}

下面是一个使用 Junit5 @ParameterizedTest 注释和 ArgumentsProvider 接口的示例,编写了一个 Factory 类为此类提供测试数据:

public class ConcatenationTest {

    @ParameterizedTest
    @ArgumentsSource(ConcatenationFactory.class)
    void should_concatenate_strings(final String a, final String b, final String expected) {
        final String result = Concatenation.concat(a, b);
        assertEquals(expected, result);
    }

    private static class ConcatenationFactory implements ArgumentsProvider {
        @Override
        public Stream<? extends Arguments> provideArguments(final ExtensionContext extensionContext) {
            return Stream.of(
                Arguments.of("Hello", "world", "Hello world"),
                Arguments.of("JUnit5", "is awesome", "JUnit5 is awesome"),
                Arguments.of("", "", " ")
            );
        }
    }
}

技巧3:使用行为驱动测试

在单元测试中,最好使用行为驱动测试(BDD)或使用 AssertJ 等库的断言来描述测试。使用 BDD,您可以清楚地表达正在测试的行为或功能,并且确保测试的理解和可读性。

示例:

下面是一个使用 AssertJ 的 BDD 风格的示例:

@Test
void whenSalaryIsLessThanThreshold_outputIsZero() {
    // Given
    int salary = 20_000;
    // When
    int tax = calculateTax(salary);
    // Then
    assertThat(tax).isZero();
}

@Test
void whenSalaryIsGreaterThanThreshold_outputIsGreaterThanZero() {
    // Given
    int salary = 70_000;
    // When
    int tax = calculateTax(salary);
    // Then
    assertThat(tax).isGreaterThan(0);
}

技巧4:使用 MockObject 或 Stubbing 单元测试

在单元测试中,您必须仅测试功能模块。但是,如果模块依赖于其他模块,则必须针对其依赖项运行测试,并使用 MockObject 或 Stubbing 技术,该技术允许您在不执行外部依赖项的情况下测试。它有助于减少测试运行时间并提高测试速度。

示例:

以下类使用一个 GreetingsService 类,用于获取问候语并添加到消息中:

public class MessageService {

    private final GreetingsService greetingsService;

    public MessageService(final GreetingsService greetingsService) {
        this.greetingsService = greetingsService;
    }

    public String getMessage(final String name) {
        final String greeting = greetingsService.getGreeting(name);
        return "Hello, " + name + "! " + greeting;
    }

}

在以下测试中,我们使用 Mockito 来模拟 GreetingsService 的依赖项和 Stubbing:

@Test
void getMessage_ShouldReturnCorrectMessage() {
    final GreetingsService mockedGreetingService = mock(GreetingsService.class);
    final MessageService messageService = new MessageService(mockedGreetingService);

    final String name = "Alice";
    final String expected = "Hello, Alice! good morning";

    when(mockedGreetingService.getGreeting(name)).thenReturn("good morning");

    final String result = messageService.getMessage(name);

    assertThat(result).isEqualTo(expected);
}

技巧5:运行单元测试的多个版本

随着时间的推移,您的代码库可能会发生变化。您应该保持您的测试套件不仅能够运行最新版本的代码,也要能够运行先前版本的代码。创建多个分支,每个分支对应于一个版本的代码,以确保它们仍容易编译,运行以及产生正确的结果。

示例:

假设我们有一个简单的 Java 类,将两个整数相加并返回值:

public class Addition {
    public static int add(int a, int b) {
        return a + b;
    }
}

我们需要在代码库多个版本中运行测试。使用 Maven 的 profile 功能,您可以轻松地在支持的不同版本中运行测试,如下面的示例:

<profiles>
    <profile>
        <id>jdk11</id>
        <activation>
            <jdk>11</jdk>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>3.0.0-M4</version>
                    <configuration>
                        <argLine>--illegal-access=deny</argLine>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
    <profile>
        <id>jdk8</id>
        <activation>
            <jdk>1.8</jdk>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.2</version>
                    <configuration>
                        <argLine>--illegal-access=permit</argLine>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

技巧6:编写可读的单元测试

当您编写可读性差的测试时,您很难理解测试的意图。同时,当测试失败时,您需要知道出现了哪种问题,而可读性差的测试将会使问题更加难以定位。为了测试易读性,您可以编写代码注释、使用描述性的变量名、等等。

示例:

以下是一个使用 Junit5 和 AssertJ 的示例,它禁用了测试方法。使用注释和描述性变量名称,提高了测试可读性:

@Disabled("needs to be refactored")
@Test
void calculatingTaxForPersonThatMakesLessThan16k_shouldReturnZero() {
    final int personSalary = 12_000;
    final int personAge = 40;
    final String personName = "John Doe";

    final Person person = new Person(personName, personAge, personSalary);
    final int result = taxCalculator.calculate(person);

    assertThat(result).isEqualTo(0);
}

技巧7:在IDE中运行单元测试

在 IDE 中遵循 TDD(测试驱动开发)流程,可以让您快速反馈并调试功能问题,而不必延迟到将代码提交到代码库中后检查问题。许多 IDE 都支持单击按钮即可运行单元测试。

示例:

当使用 IntelliJ IDEA 编辑器时,点击 Test 按钮或使用快捷键 Ctrl + Shift + F10 即可运行单元测试。如果您更改代码,并保存文件,IntelliJ IDEA 将自动重新运行相关测试。

这就是“Java程序员如何编写更好的单元测试的7个技巧”的攻略,希望对您的测试工作有所帮助!

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java程序员如何编写更好的单元测试的7个技巧 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Json实现传值到后台代码实例

    下面我将为你详细讲解“Json实现传值到后台代码实例”的完整攻略。 什么是Json JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。JSON采用键值对的方式来表达数据,常用于前后端之间数据的传输。 Json实现传值到后台的方法 Json实现传值到后台的方法通常是通过Aj…

    Java 2023年5月26日
    00
  • Mybatis使用MySQL模糊查询时输入中文检索不到结果怎么办

    为了解决”Mybatis使用MySQL模糊查询时输入中文检索不到结果”的问题,我们需要在Mybatis配置文件中进行一些特定的设置。 1.在Mybatis的配置文件中添加如下代码: <configuration> <settings> <setting name="jdbcTypeForNull" value…

    Java 2023年6月1日
    00
  • Java语法基础之运算符学习笔记分享

    欢迎来到Java语法基础之运算符学习笔记分享。在本篇笔记中,我们将简要介绍Java的运算符,包括算术运算符、位运算符、赋值运算符、关系运算符、逻辑运算符和三目运算符。 算术运算符 Java中有七个算术运算符:加、减、乘、除、取余、自增、自减。它们可以用于数学运算。 以下是示例代码: int a = 10; int b = 4; System.out.prin…

    Java 2023年5月30日
    00
  • Java中循环冗余校验(CRC32)的实现

    Java中循环冗余校验(CRC32)的实现 简介 循环冗余校验(CRC)是一种根据数据产生校验码的技术,它主要用于检测或者校验数据,以确定数据的完整性和准确性。在Java中,CRC32是循环冗余校验算法的一种常用实现。 实现步骤 1. 使用java.util.zip.CRC32类 Java提供了java.util.zip.CRC32类来实现CRC32算法。这…

    Java 2023年5月19日
    00
  • Springboot单体架构http请求转换https请求来支持微信小程序调用接口

    让我们来详细讲解“Springboot单体架构http请求转换https请求来支持微信小程序调用接口”的攻略。 背景介绍 微信小程序在与后端交互时,要求所有的接口都必须使用HTTPS协议,而SpringBoot单体架构默认是使用HTTP协议的。所以,我们需要将HTTP请求转换为HTTPS请求,来支持微信小程序调用接口。 实现过程 以下是实现过程的详细步骤: …

    Java 2023年5月23日
    00
  • java之assert关键字用法案例详解

    Java之assert关键字用法案例详解 概述 本文将详细讲解Java中的assert关键字用法,并给出案例说明。 assert是Java语言的一个关键字,用于进行程序断言。assert关键字的作用是在开发和调试期间,为程序员提供了一个简单有效的集成测试方法,可以确保代码的正确性和程序的可靠性。 assert的语法格式 assert语法格式如下: asser…

    Java 2023年5月26日
    00
  • Maven导入本地jar包的实现步骤

    下面是Maven导入本地jar包的实现步骤的攻略。 步骤 1. 安装本地jar包 在Maven项目中引入本地jar包前,需要先在本地安装好该jar包。在命令行中使用Maven提供的install命令自动将jar包安装到本机的Maven仓库中。 mvn install:install-file -Dfile=<path-to-file> -Dgro…

    Java 2023年5月20日
    00
  • 在Flash中实现物体运动的三种方法介绍(AS)

    当使用Flash软件制作动画或游戏时,需要使用一些方法来实现物体的运动效果。在ActionScript编程中,也可以使用一些代码来实现物体的移动,以下是三种常用的方法: 一、基于坐标移动 这种方法是指直接修改物体的坐标值,实现物体的移动。以AS3为例,在代码中可以使用如下方法: object.x = object.x + 10; // 将物体沿着 x 轴正方…

    Java 2023年6月15日
    00
合作推广
合作推广
分享本页
返回顶部