Java Testing tools for 2024
Tags: java, testing, programming, tutorial
Published: 2024-02-10 23:34:16

## AssertJ

Extension of Junit testing library that provides assertion methods. In a fluent way you can assert:

- Common types: Optional, Predicates, Streams, Itreable

- Primitive types

- Java 8 Temporal Types

- Atomic Types
 
It adds to the redability of the tests.

Some of the features

- Recursive comparision by field. Compares two objects from different classes. Like entity and dto objects. AssertJ goes filed by filed on objects and compare values of the fileds.
```java
    @Test
    public void testPerson() {
        var p1 = new Person("John", 20);
        var p2 = new PersonDto("John", 20);

        assertThat(p1).usingRecursiveComparison().isEqualTo(p2);

      //  assertThat(p1).isEqualTo(p2);
    }
```

- Soft assertions. Collects all assertion errors instead of stopping at the first one. 
```java
    @Test
    public void softAssertionTest() {
        var p1 = new Person("John 2", 20);

        SoftAssertions.assertSoftly(soft -> {
            soft.assertThat(p1.getName()).isEqualTo("Not John");
            soft.assertThat(p1.getAge()).isEqualTo(22);
        });
    }
```

```
Multiple Failures (2 failures)
-- failure 1 --
expected: "Not John"
 but was: "John 2"
at PersonTest.lambda$softAssertionTest$0(PersonTest.java:28)
-- failure 2 --
expected: 22
 but was: 20
at PersonTest.lambda$softAssertionTest$0(PersonTest.java:29)
```
- Custom assertions. Create your own validation.
```java
class PersonAssertion extends AbstractAssert<PersonAssertion, Person> {
    protected PersonAssertion(Person actual) {
        super(actual, PersonAssertion.class);
    }
    public static PersonAssertion assertThat(Person person) {
        return new PersonAssertion(person);
    }
    public PersonAssertion isAdult() {
        if (actual.getAge() < 18) {
            failWithMessage("Not adult");
        }
        return this;
    }
}

// ... 
// in the test class 

    @Test
    public void customAssertionTest() {
        var p1 = new Person("John 2", 20);
        PersonAssertion.assertThat(p1).isAdult();
    }
```
## Rest-Assured

Java API testing library for REST based services based on the given-when-then keywords (not BDD) - DSL for API testing.

```java
    @Test
    public void testGet() {
        Person personResponse =
            when().
                get("/person/1").
            then().
                statusCode(200).
                extract().as(Person.class);

        assertThat(personResponse.getName()).isEqualTo("John");
    }
```


We can fast create the test architecture and decrease the test maintenance by:

- Using the openapi-generator to create the client based on REST Assured

- Create a service layer in the test project 

## Awaitility

During the test to wait for an asynchronous system (RabbitMQ, Apache Kafka, Redis...) to complete the request. You can: 
- Create conditions to wait
- Check fields
- Support for Atomic
- Ignoring and checking exceptions
- Integrate with AssertJ

```java
@Test
public void updatesCustomerStatus() {
    // Publish an asynchronous message to a broker (e.g. RabbitMQ):
    messageBroker.publishMessage(updateCustomerStatusMessage);
    // Awaitility lets you wait until the asynchronous operation completes:
    await().atMost(5, SECONDS).until(customerStatusIsUpdated());
    ...
}
```

## WireMock

Open source tool for API mock testing. It constructs an HTTP server that we can connect to as we would to an actual web service.

Instead of mocking something you need, that will be duplicated across the teams you can implement a Service Virtualization approach using WireMock to share the same mock across multiple teams.

## PiTest (PIT)

Mutation testing library. It tryes detect faults in the code base on a series code chaged. Showing you if your code base had lived of killed mutations: 

- Lived mutations: indicated you have something to work on

- Killed mutatiuons: the change applied is covered

When the application code changes, it should produce different results and cause the unit tests to fail. If a unit test does not fail in this situation, it may indicate an issue with the test suite. PiTest changes the code (mutates the code): 
- Conditional Boundary
- Increment
- Math