Custom Assertions with AssertJ – 使用AssertJ的自定义断言

最后修改: 2018年 2月 5日

中文/混合/英文(键盘快捷键:t)

 

1. Overview

1.概述

In this tutorial, we’ll walk through creating custom AssertJ assertions; the AssertJ’s basics can be found here.

在本教程中,我们将通过创建自定义AssertJ断言;AssertJ的基础知识可以在这里找到。

Simply put, custom assertions allow creating assertions specific to our own classes, allowing our tests to better reflect the domain model.

简单地说,自定义断言允许创建特定于我们自己的类的断言,使我们的测试能够更好地反映领域模型。

2. Class Under Test

2.被测类

Test cases in this tutorial will be built around the Person class:

本教程中的测试用例将围绕Person类建立。

public class Person {
    private String fullName;
    private int age;
    private List<String> nicknames;

    public Person(String fullName, int age) {
        this.fullName = fullName;
        this.age = age;
        this.nicknames = new ArrayList<>();
    }

    public void addNickname(String nickname) {
        nicknames.add(nickname);
    }

    // getters
}

3. Custom Assertion Class

3.自定义断言类

Writing a custom AssertJ assertion class is pretty simple. All we need to do is to declare a class that extends AbstractAssert, add a required constructor, and provide custom assertion methods.

编写一个自定义的AssertJ断言类是非常简单的。我们需要做的就是声明一个扩展AbstractAssert的类,添加一个必要的构造函数,并提供自定义断言方法。

The assertion class must extend the AbstractAssert class to give us access to essential assertion methods of the API, such as isNotNull and isEqualTo.

断言类必须扩展AbstractAssert类,以便让我们访问API的基本断言方法,例如isNotNullisEqualTo

Here’s the skeleton of a custom assertion class for Person:

这里是Person的自定义断言类的骨架。

public class PersonAssert extends AbstractAssert<PersonAssert, Person> {

    public PersonAssert(Person actual) {
        super(actual, PersonAssert.class);
    }

    // assertion methods described later
}

We must specify two type arguments when extending the AbstractAssert class: the first is the custom assertion class itself, which is required for method chaining, and the second is the class under test.

在扩展AbstractAssert类时,我们必须指定两个类型参数:第一个是自定义断言类本身,这是方法链所需要的,第二个是被测类。

To provide an entry point to our assertion class, we can define a static method that can be used to start an assertion chain:

为了给我们的断言类提供一个入口,我们可以定义一个静态方法,用来启动一个断言链。

public static PersonAssert assertThat(Person actual) {
    return new PersonAssert(actual);
}

Next, we’ll go over several custom assertions included in the PersonAssert class.

接下来,我们将讨论PersonAssert类中包含的几个自定义断言。

The first method verifies that the full name of a Person matches a String argument:

第一个方法验证一个Person的全名是否与一个String参数相匹配。

public PersonAssert hasFullName(String fullName) {
    isNotNull();
    if (!actual.getFullName().equals(fullName)) {
        failWithMessage("Expected person to have full name %s but was %s", 
          fullName, actual.getFullName());
    }
    return this;
}

The following method tests if a Person is an adult based on its age:

下面的方法根据Person年龄测试其是否为成年人。

public PersonAssert isAdult() {
    isNotNull();
    if (actual.getAge() < 18) {
        failWithMessage("Expected person to be adult");
    }
    return this;
}

The last checks for the existence of a nickname:

最后一个检查是否存在nickname

public PersonAssert hasNickName(String nickName) {
    isNotNull();
    if (!actual.getNickNames().contains(nickName)) {
        failWithMessage("Expected person to have nickname %s", 
          nickName);
    }
    return this;
}

When having more than one custom assertion class, we may wrap all assertThat methods in a class, providing a static factory method for each of the assertion classes:

当有多个自定义断言类时,我们可以将所有assertThat方法封装在一个类中,为每个断言类提供一个静态工厂方法。

public class Assertions {
    public static PersonAssert assertThat(Person actual) {
        return new PersonAssert(actual);
    }

    // static factory methods of other assertion classes
}

The Assertions class shown above is a convenient entry point to all custom assertion classes.

上面显示的Assertions类是所有自定义断言类的一个方便的入口。

Static methods of this class have the same name and are differentiated from each other by their parameter type.

该类的静态方法具有相同的名称,并通过其参数类型相互区别。

4. In Action

4.在行动中

The following test cases will illustrate the custom assertion methods we created in the previous section. Notice that the assertThat method is imported from our custom Assertions class, not the core AssertJ API.

下面的测试案例将说明我们在上一节创建的自定义断言方法。请注意,assertThat方法是从我们的自定义Assertions类中导入的,而不是核心AssertJ API。

Here’s how the hasFullName method can be used:

下面是如何使用hasFullName方法。

@Test
public void whenPersonNameMatches_thenCorrect() {
    Person person = new Person("John Doe", 20);
    assertThat(person)
      .hasFullName("John Doe");
}

This is a negative test case illustrating the isAdult method:

这是一个说明isAdult方法的负面测试案例。

@Test
public void whenPersonAgeLessThanEighteen_thenNotAdult() {
    Person person = new Person("Jane Roe", 16);

    // assertion fails
    assertThat(person).isAdult();
}

and another test demonstrating the hasNickname method:

和另一个演示hasNickname方法的测试。

@Test
public void whenPersonDoesNotHaveAMatchingNickname_thenIncorrect() {
    Person person = new Person("John Doe", 20);
    person.addNickname("Nick");

    // assertion will fail
    assertThat(person)
      .hasNickname("John");
}

5. Assertions Generator

5.断言生成器

Writing custom assertion classes corresponding to the object model paves the way for very readable test cases.

编写与对象模型相对应的自定义断言类,为非常可读的测试案例铺平道路。

However, if we have a lot of classes, it would be painful to manually create custom assertion classes for all of them. This is where the AssertJ assertions generator comes into play.

然而,如果我们有很多类,为所有的类手动创建自定义断言类是很痛苦的。这就是AssertJ断言生成器发挥作用的地方。

To use the assertions generator with Maven, we need to add a plugin to the pom.xml file:

要在Maven中使用断言生成器,我们需要在pom.xml文件中添加一个插件。

<plugin>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-assertions-generator-maven-plugin</artifactId>
    <version>2.1.0</version>
    <configuration>
        <classes>
            <param>com.baeldung.testing.assertj.custom.Person</param>
        </classes>
    </configuration>
</plugin>

The latest version of the assertj-assertions-generator-maven-plugin can be found here.

最新版本的assertj-assertions-generator-maven-plugin可以在这里找到。

The classes element in the above plugin marks classes for which we want to generate assertions. Please see this post for other configurations of the plugin.

上述插件中的classes元素标志着我们要为其生成断言的类。关于该插件的其他配置,请参见这篇文章

The AssertJ assertions generator creates assertions for each public property of the target class. The specific name of each assertion method depends on the field’s or property’s type. For a complete description of the assertions generator, check out this reference.

AssertJ断言发生器为目标类的每个公共属性创建断言。每个断言方法的具体名称取决于字段或属性的类型。有关断言生成器的完整描述,请查看本参考资料

Execute the following Maven command in the project base directory:

在项目基础目录下执行以下Maven命令。

mvn assertj:generate-assertions

We should see assertion classes generated in the folder target/generated-test-sources/assertj-assertions. For example, the generated entry point class for the generated assertions looks like this:

我们应该看到在target/generated-test-sources/assertj-assertions文件夹中生成的断言类。例如,生成的断言的入口点类看起来像这样。

// generated comments are stripped off for brevity

package com.baeldung.testing.assertj.custom;

@javax.annotation.Generated(value="assertj-assertions-generator")
public class Assertions {

    @org.assertj.core.util.CheckReturnValue
    public static com.baeldung.testing.assertj.custom.PersonAssert
      assertThat(com.baeldung.testing.assertj.custom.Person actual) {
        return new com.baeldung.testing.assertj.custom.PersonAssert(actual);
    }

    protected Assertions() {
        // empty
    }
}

Now, we can copy the generated source files to the test directory, then add custom assertion methods to satisfy our testing requirements.

现在,我们可以把生成的源文件复制到测试目录,然后添加自定义断言方法,以满足我们的测试要求。

One important thing to notice is that the generated code isn’t guaranteed to be entirely correct. At this point, the generator isn’t a finished product, and the community is working on it.

需要注意的一件事是,生成的代码并不能保证完全正确。在这一点上,生成器并不是一个成品,社区正在对它进行努力。

Hence, we should use the generator as a supporting tool to make our life easier instead of taking it for granted.

因此,我们应该把发电机作为一个辅助工具,使我们的生活更容易,而不是把它当作理所当然。

6. Conclusion

6.结论

In this tutorial, we’ve shown how to create custom assertions for creating readable test code with the AssertJ library, both manually and automatically.

在本教程中,我们展示了如何使用AssertJ库创建自定义断言,以创建可读的测试代码,包括手动和自动。

If we have just a small number of classes under test, the manual solution is enough; otherwise, the generator should be used.

如果我们只有少量的被测类,手工解决就足够了;否则就应该使用生成器。

And, as always, the implementation of all the examples and code snippets can be found over on GitHub.

而且,像往常一样,所有的例子和代码片段的实现都可以在GitHub上找到over

« Previous

AssertJ’s Java 8 Features

“/strong> Previous

AssertJ的Java 8特点