JUnit 5 - AssertJ (Phần 3)

31 tháng 05, 2021 - 2417 lượt xem

Trong bài viết này chúng ta sẽ khám phá AssertJ - một opensource - thư viện điều khiển được sử dụng để viết các assertions trong Java tests

Giới thiệu về AssertJ

AssertJ là một thư viện để đơn giản hóa việc viết các assertions. Nó cũng cải thiện khả năng đọc các câu lệnh assertion. AssertJ có fluent interface cho assertions, giúp bạn dễ dàng viết code. Method cơ sở cho các AssertJ là assertThat.


Cài đặt AssertJ trong dự án Maven

Để sử dụng AssertJ, bạn cần thêm dependency của JUnit và file pom.xml

<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.4.1</version>
    <scope>test</scope>
</dependency>

Dependency này chỉ bao gồm các assertions Java cơ bản. Nếu bạn muốn sử dụng assertion nâng cao, bạn sẽ phải thêm modules bổ sung riêng


Sử dụng AssertJ

Viết assertions

Để viết assertions, bạn luôn cần bắt đầu bằng cách chuyển object của mình tới phương thức assertThat() và thực hiện theo các assertions thực tế.

assertThat(anyReferenceOrValue);

Để bắt đầu, ta cần import:

import static org.assertj.core.api.Java6Assertions.assertThat;

Ví dụ:

@Test
@DisplayName("TestAssertJ")
void sampleAssertion(){
    assertThat("This is my sample Test").isNotNull()
            .startsWith("This")
            .contains("sample")
            .endsWith("Test");
}

Result:

Object Assertions

Các đối tượng có thể được so sánh theo nhiều cách khác nhau hoặc để xác định hai object là bằng nhau

Ví dụ mình có:

public class Dog {
    private String name;
    private double weight;

    public Dog(String name, double weight) {
        this.name = name;
        this.weight = weight;
    }
}

Giờ hãy thử so sánh hai đối tượng sau

@Test
@DisplayName("TestObject")
void testMethod_Objects(){
    Dog mic = new Dog("Mic", 10.5);
    Dog micClone = new Dog("Mic", 10.5);

    //Test will fail as isEqualTo() compares object reference
    assertThat(mic).isEqualTo(micClone);
}

Tại đây mình sử dụng isEqualTo() để so sánh hai object là micmicClone. Tuy nhiên test không thành công bởi isEqualTo() so sánh các tham chiếu đối tượng chứ không so sánh nội dung

Thay vào đó nếu chúng ta muốn so sánh nội dung của chúng, chúng ta có thể sử dụng isEqualToComparingFieldByFieldRecursenty():

assertThat(mic).isEqualToComparingFieldByFieldRecursively(micClone);

Hoặc nếu chỉ muốn so sánh một thuộc tính ta có thể sử dụng isEqualToComparingOnlyGivenFields()

@Test
@DisplayName("TestObject")
void testMethod_Objects(){
    Dog mic = new Dog("Mic", 10.5);
    Dog otherDog = new Dog("Mic", 15.5);

    //Only compare name
    assertThat(mic).isEqualToComparingOnlyGivenFields(otherDog, "name");
}

Ở đây mình chỉ so sánh thuộc tính name

Array Assertions

Đối với mảng, có nhiều cách để khẳng định rằng nội dung của chúng tốn tại. Một trong những assertions phổ biến nhất là kiểm tra xem mảng có chứa phần tử đã cho hay không

@Test
@DisplayName("TestArray")
void testMethod_Arrays(){
    String [] countries = new String[]{"Russia", "Viet Nam", "America", "Japan", "China"};
    assertThat(countries).contains("Viet Nam");
}

Hoặc nếu mảng không trống:

assertThat(countries).isNotEmpty();

Hoặc nếu mảng bắt đầu với một phần tử nhất định:

assertThat(countries).startsWith("Russia");

Hoặc kết hợp nhiều assertions:

assertThat(countries).isNotEmpty() //Array is not empty
        .contains("Viet Nam")      //contains "Viet Nam" element
        .doesNotContainNull()      //does not contains any nulls
        .containsSequence("America", "Japan");  //contains sequence of element "America", "Japan"

Strings Assertions

Có nhiều assertions phổ biến đối với chuỗi, hãy xem ví dụ sau:

@Test
@DisplayName("TestStrings")
void testMethod_Strings(){
    String say = "Chị không muốn nhiêu bug nhưng mà bug nhiều nên chị phải fix";

    assertThat(say).isNotNull()     //String is not empty
            .startsWith("Chị")      //Start with "Chị
            .doesNotContain("Anh")  //Not contain "Anh"
            .endsWith("fix");       //End with "fix"
}

Ở đây mình kết hợp nhiều assertion với nhau bao gồm isNotNull() để kiểm tra chuỗi có null không, startsWith() chuỗi bắt đầu với từ “Chị”, doesNotContain() không chứa từ “Anh”, endsWith() chuỗi kết thúc bằng từ “fix”

Ngoài ra, chúng ta còn có thể so sánh với isEqualTo()

String say = "Chị không muốn nhiêu bug nhưng mà bug nhiều nên chị phải fix";
String sayClone = say;

assertThat(say).isEqualTo(sayClone);

Numbers Assertions

Number Assertion nhằm so sánh các giá trị số trong hoặc không có khoảng chênh lệch nhất định. Ví dụ, nếu bạn muốn kiểm tra xem hai giá trị có bằng nhau theo một độ chính xác nhất định hay không, chúng ta có thể thực hiện như sau:

@Test
@DisplayName("TestNumbers")
void testMethod_Numbers(){
    Double value = 12.0;
    assertThat(value).isEqualTo(12.2, withPrecision(1d));
}

Tại đây ta có độ chính xác là 1.

Hoặc có offset

assertThat(value).isCloseTo(15.0, Offset.offset(3d));

Hoặc value nằm trong một khoảng, ví dụ:

assertThat(value).isBetween(10.0, 15.0); //value >= 10.0 and value <= 15.0

Hoặc

assertThat(value).isStrictlyBetween(10.0, 15.0); //value > 10.0 and value < 15.

Map Assertions

Map Assertions cho phép bạn kiểm tra xem map có chứa entry, tập hợp các entry, hoặc key/values riêng biệt hay không

Ví dụ dưới đây liệt kê một số assertions chúng ta hay sử dụng đối với Map:

@Test
@DisplayName("TestMap")
void testMethod_Map(){
    Map<String, String> countryCityMap = new HashMap<String, String>();
    countryCityMap.put("Viet Nam", "Ha Noi");
    countryCityMap.put("Japan", "Tokyo");
    countryCityMap.put("Canada", "Ottawa");
    countryCityMap.put("Australian", "Canberra");

    assertThat(countryCityMap).isNotEmpty()          //Map is not empty
            .hasSize(4)                              //Size = 4
            .doesNotContainValue("Sydney")           //Does not contain value "Sydney"
            .contains(entry("Viet Nam", "Ha Noi"))   //Contain ("Viet Nam", "Ha Noi")
            .containsKey("Japan")                    //Contains key "Japan"
            .containsValue("Ottawa");                //Contains value Ottawa
}

Throwable assertions

Throwable assertions cho phép kiểm tra các message của ngoại lệ, stack trade, kiểm tra nguyên nhân hoặc xác minh nếu một ngoại lệ được đưa ra

Ví dụ:

@Test
@DisplayName("TestThrowable")
void testMethod_Throwable(){
    IllegalArgumentException illegalArgumentException = new IllegalArgumentException("This is error message");
    IllegalArgumentException illegalArgumentExceptionWithCause = new IllegalArgumentException("This is error message", new IOException());

    assertThat(illegalArgumentException).hasNoCause()
            .hasMessageStartingWith("T")
            .hasMessageEndingWith("e");
    assertThat(illegalArgumentExceptionWithCause).hasCauseExactlyInstanceOf(IOException.class);
}

Class Assertions và miêu tả Assertions

Class Assertion chủ yếu thực hiện các việc kiểm tra các trường, method, có annotation hay không, có là interface, có là lớp final,…

Chúng ta có thể tạo ra các mô tả cho assertions của mình với phương thức as()

@Test
@DisplayName("TestClass")
void testMethod_Class(){
    Dog mic = new Dog("Mic", 10.5);
    assertThat(Dog.class).isNotAnnotation()
            .isNotFinal()
            .hasDeclaredFields("name")
            .hasDeclaredFields("weight");
    assertThat(mic.getWeight()).as("%d's weight need to be more than 0", mic.getName())
            .isGreaterThan(0);
}

Trong bài viết này mình đã giới thiệu tới các bạn về AssertJ, cách sử dụng AssertJ đối với Object, number, array, String, class,…

Code tham khảo: https://github.com/EriChannel/JUnit-5-Tutorial/tree/main/02-AssertJ/Demo

Tham khảo Lộ trình Java Spring Boot Full Stack 7 tháng dành cho người chuyển ngành, chuyển nghề, sinh viên CNTT năm 3,4 muốn học xong đi làm sớm để tích lũy kinh nghiệm.
Liên hệ tư vấn: Ms Mẫn - 0963023185 - manpham@techmaster.vn

Bình luận

avatar
Trịnh Minh Cường 2021-05-31 04:56:45.151361 +0000 UTC

Bài hay đó cô giáo.

Avatar
* Vui lòng trước khi bình luận.
Ảnh đại diện
  +8 Thích
+8