使用 AssertJ 进行单元测试的提示

这篇具有很好参考价值的文章主要介绍了使用 AssertJ 进行单元测试的提示。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

单元测试已成为开发的标准部分。许多工具可以以许多不同的方式用于它。本文演示了一些提示,或者说,对我来说效果很好的最佳实践。

在本文中,您将了解
如何使用 JUnit 和 Assert 框架编写干净且可读的单元测试
在某些情况下如何避免假阳性测试
编写单元测试时应避免的事项
不要过度使用 NPE 检查
我们都倾向于在主代码中尽可能避免 NullPointerException,因为它可能会导致丑陋的后果。我相信我们主要关心的不是在测试中避免NPE。我们的目标是以干净、可读和可靠的方式验证被测组件的行为。

不良做法
过去很多次,即使不需要断言,我也使用过断言,如下例所示:isNotNull

@Test
public void getMessage() {
	assertThat(service).isNotNull();
	assertThat(service.getMessage()).isEqualTo("Hello world!");
}

此测试产生如下错误:

java.lang.AssertionError: 
Expecting actual not to be null
	at com.github.aha.poc.junit.spring.StandardSpringTest.test(StandardSpringTest.java:19)

良好做法
尽管附加断言并不真正有害,但由于以下原因,应避免使用:isNotNull

它不会增加任何附加值。它只是需要阅读和维护的更多代码。
无论如何,测试都会失败,我们看到了失败的真正根本原因。该测试仍然实现了其目的。servicenull
使用 AssertJ 断言时,生成的错误消息甚至更好。
请参阅下面修改后的测试断言。

@Test
public void getMessage() {
	assertThat(service.getMessage()).isEqualTo("Hello world!");
}

修改后的测试会产生如下错误:

java.lang.NullPointerException: Cannot invoke "com.github.aha.poc.junit.spring.HelloService.getMessage()" because "this.service" is null
	at com.github.aha.poc.junit.spring.StandardSpringTest.test(StandardSpringTest.java:19)

注意:该示例可以在 SimpleSpringTest 中找到。

断言值而不是结果
有时,我们会编写一个正确的测试,但以“糟糕”的方式。这意味着测试完全按预期工作并验证了我们的组件,但失败没有提供足够的信息。因此,我们的目标是断言价值而不是比较结果。

不良做法
让我们看看几个这样的糟糕测试:

// #1
assertThat(argument.contains("o")).isTrue();

// #2
var result = "Welcome to JDK 10";
assertThat(result instanceof String).isTrue();

// #3
assertThat("".isBlank()).isTrue();

// #4
Optional<Method> testMethod = testInfo.getTestMethod();
assertThat(testMethod.isPresent()).isTrue();

上述测试中的一些错误如下所示。

#1
Expecting value to be true but was false
	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
	at com.github.aha.poc.junit5.params.SimpleParamTests.stringTest(SimpleParamTests.java:23)
  
#3
Expecting value to be true but was false
	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
	at com.github.aha.poc.junit5.ConditionalTests.checkJdk11Feature(ConditionalTests.java:50)

良好做法
使用 AssertJ 及其流畅的 API 可以轻松解决问题。上面提到的所有情况都可以很容易地改写为:

// #1
assertThat(argument).contains("o");

// #2
assertThat(result).isInstanceOf(String.class);

// #3
assertThat("").isBlank();

// #4
assertThat(testMethod).isPresent();

与前面提到的完全相同的错误现在提供了更多价值。

#1
Expecting actual:
  "Hello"
to contain:
  "f" 
	at com.github.aha.poc.junit5.params.SimpleParamTests.stringTest(SimpleParamTests.java:23)
    
#3
Expecting blank but was: "a"
	at com.github.aha.poc.junit5.ConditionalTests.checkJdk11Feature(ConditionalTests.java:50)

注意:该示例可以在 SimpleParamTests 中找到。

与组相关的断言在一起
断言链接和相关的代码缩进对测试的清晰度和可读性有很大帮助。

不良做法
当我们编写测试时,我们最终会得到正确但可读性较差的测试。让我们想象一个测试,我们想要在其中查找国家/地区并进行以下检查:

计算找到的国家/地区。
使用多个值断言第一个条目。
此类测试可能如下所示:

@Test
void listCountries() {
	List<Country> result = ...;

	assertThat(result).hasSize(5);
	var country = result.get(0);
	assertThat(country.getName()).isEqualTo("Spain");
	assertThat(country.getCities().stream().map(City::getName)).contains("Barcelona");

良好做法
尽管前面的测试是正确的,但我们应该通过将相关断言组合在一起(第 9-11 行)来大大提高可读性。这里的目标是断言一次,并根据需要编写许多链接断言。请参阅下面的修改版本。result

@Test
void listCountries() {
	List<Country> result = ...;

	assertThat(result)
		.hasSize(5)
		.singleElement()
		.satisfies(c -> {
			assertThat(c.getName()).isEqualTo("Spain");
			assertThat(c.getCities().stream().map(City::getName)).contains("Barcelona");
		});
}

注意:该示例可以在 CountryRepositoryOtherTests 中找到。

防止误报成功测试
当使用任何带有参数的断言方法时,参数也必须包含在使用者中。否则,测试将一直通过 - 即使比较失败,这意味着错误的测试。仅当断言引发 or 异常时,测试才会失败。我想这很清楚,但很容易忘记它并写错测试。它不时发生在我身上。ThrowingConsumer assertThat RuntimeException AssertionError

不良做法
假设我们有几个国家/地区代码,我们想要验证每个代码是否满足某些条件。在我们的虚拟案例中,我们想断言每个国家/地区代码都包含“a”字符。正如你所看到的,这是无稽之谈:我们有大写的代码,但我们没有在断言中应用不区分大小写。

@Test
void assertValues() throws Exception {
	var countryCodes = List.of("CZ", "AT", "CA");
	
	assertThat( countryCodes )
		.hasSize(3)
		.allSatisfy(countryCode -> countryCode.contains("a"));
}

令人惊讶的是,我们的测试成功通过了。

使用 AssertJ 进行单元测试的提示,单元测试,java,junit
良好做法
如本节开头所述,我们的测试可以通过消费者中的附加功能轻松纠正(第 7 行)。正确的测试应该是这样的:assertThat

@Test
void assertValues() throws Exception {
	var countryCodes = List.of("CZ", "AT", "CA");
	
	assertThat( countryCodes )
		.hasSize(3)
		.allSatisfy(countryCode -> assertThat( countryCode ).containsIgnoringCase("a"));
}

现在,测试按预期失败,并显示正确的错误消息。

java.lang.AssertionError: 
Expecting all elements of:
  ["CZ", "AT", "CA"]
to satisfy given requirements, but these elements did not:

"CZ"
error: 
Expecting actual:
  "CZ"
to contain:
  "a"
 (ignoring case)
	at com.github.aha.sat.core.clr.AppleTest.assertValues(AppleTest.java:45)

链断言
最后一个提示不是真正的实践,而是建议。应使用 AssertJ fluent API 来创建更具可读性的测试。

非链接断言
让我们考虑一下 test,其目的是测试组件的日志记录。这里的目标是检查:listLogs

断言收集的日志数
断言存在和日志消息DEBU GINFO

@Test
void listLogs() throws Exception {
	ListAppender<ILoggingEvent> logAppender = ...;
	
	assertThat( logAppender.list ).hasSize(2);
	assertThat( logAppender.list ).anySatisfy(logEntry -> {
			assertThat( logEntry.getLevel() ).isEqualTo(DEBUG);
			assertThat( logEntry.getFormattedMessage() ).startsWith("Initializing Apple");
		});
	assertThat( logAppender.list ).anySatisfy(logEntry -> {
			assertThat( logEntry.getLevel() ).isEqualTo(INFO);
			assertThat( logEntry.getFormattedMessage() ).isEqualTo("Here's Apple runner" );
		});
}

链接断言
通过上面提到的 Fluent API 和链接,我们可以这样更改测试:

@Test
void listLogs() throws Exception {
	ListAppender<ILoggingEvent> logAppender = ...;
	
	assertThat( logAppender.list )
		.hasSize(2)
		.anySatisfy(logEntry -> {
			assertThat( logEntry.getLevel() ).isEqualTo(DEBUG);
			assertThat( logEntry.getFormattedMessage() ).startsWith("Initializing Apple");
		})
		.anySatisfy(logEntry -> {
			assertThat( logEntry.getLevel() ).isEqualTo(INFO);
			assertThat( logEntry.getFormattedMessage() ).isEqualTo("Here's Apple runner" );
		});
}

注意:该示例可在 AppleTest 中找到。

摘要和源代码
AssertJ 框架为其流畅的 API 提供了很多帮助。在本文中,提供了一些技巧和提示,以产生更清晰、更可靠的测试。请注意,这些建议大多是主观的。这取决于个人喜好和代码风格。文章来源地址https://www.toymoban.com/news/detail-849361.html

到了这里,关于使用 AssertJ 进行单元测试的提示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用Junit进行单元测试的简单例子

    首先新建一个工程,选择合适的路径和JDK版本,其它默认就行。 把Main.java内容改为如下。    后面就是对add方法增加单元测试 在project窗口中右击项目,在菜单中选择:New - Directory 在弹出的提示框中输入目录名:test 。 然后右击 project窗口中 test 目录,在弹出菜单中选择:

    2024年02月09日
    浏览(56)
  • IDEA使用Junit4进行单元测试

            单元测试不仅能帮我们验证代码逻辑,还可以通过执行时间进行快速筛选不合格代码并进行优化。核心模块的代码的单元测试覆盖率要达到100%,其他模块代码的单元测试覆盖率需要达到60%。下面将介绍在IDEA上使用Junit4进行单元测试的方法: 一、安装JunitGenerator2插件

    2023年04月16日
    浏览(40)
  • 在Idea中使用JUnit进行单元测试

    JUnit是Java中最常用的单元测试框架之一,它可以帮助开发人员编写高效、可靠的测试代码。在Idea集成开发环境中,我们可以方便地使用JUnit来编写和运行单元测试。本文将介绍如何在Idea中使用JUnit进行单元测试,并附带相应的源代码示例。 步骤一:添加JUnit依赖 首先,我们需

    2024年02月03日
    浏览(53)
  • 在Idea中使用Junit4进行单元测试

    #初学者,为了对知识进行巩固写这个文章,有问题欢迎指出,欢迎讨论 在Setting - Plugins - Marketplace中搜索JUnit,点击Apply后重启Idea 创建的类和文件夹 按照这个顺序就可以啦 点击OK后,在我们的Test文件夹中就出现了一个测试文件

    2024年02月03日
    浏览(51)
  • 在一个maven项目中使用maven命令进行junit单元测试

    如何在一个maven项目中使用maven命令进行junit单元测试? 首先确定一个maven项目的结构: 包含源代码目录src/main/java. 配置目录src/main/resources. 测试代码目录src/test. 目录结构可视化如下: 假定demo.java内容如下所示 我们要测试这个demo类, 可以在demoTest.java中写以下代码 然后就可以通过

    2023年04月21日
    浏览(53)
  • Spring Boot使用JUnit和Mockito进行Service层单元测试

      在平时的开发当中,一个项目往往包含了大量的方法,可能有成千上万个。如何去保证这些方法产生的结果是我们想要的呢?那么在SpringBoot项目中我们是如何对Service层的方法进行测试的呢?   单元测试是一种软件测试方法,用于测试代码的最小可测试单元。在Java开发

    2024年02月03日
    浏览(52)
  • Java中的JUnit单元测试方法的使用

    选中当前工程 - 右键选择:build path - add libraries - JUnit 4 - 下一步 创建Java类,进行单元测试。 此时的Java类要求:① 此类是public的 ②此类提供公共的无参的构造器 此类中声明单元测试方法。 此时的单元测试方法:方法的权限是public,没有返回值,没有形参。 此单元测试方法上

    2024年02月14日
    浏览(39)
  • Java - 单元测试及Junit的使用讲解及练习

    目录 🐶2.1 什么是单元测试 🐶2.2 测试分类: 1. 🥙黑盒测试 2. 🥙白盒测试 🐶2.3 Junit介绍 🐶2.4 Junit的基本使用步骤:(默认使用maven创建项目) 1. 🥙pom.xml中引入依赖:  2. 🥙示例编写一个java程序: 3. 🥙在测试类方法上添加注解 @Test。 4. 🥙点击测试运行  5. 🥙查看运行结果

    2024年01月23日
    浏览(50)
  • 软件测试--应用JUnit进行单元测试

    JUnit是一个开源的Java编程语言的单元测试框架,最初由 Erich Gamma 和 Kent Beck 编写。Junit测试是一种白盒测试工具。JUnit是一套框架,继承TestCase类,就可以用Junit进行自动测试了。具有JUnit经验对于应用“测试驱动开发(TDD)”的程序开发模型是非常重要的。 JUnit本质上是一套框

    2023年04月12日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包