DEV Community

ivan.gavlik
ivan.gavlik

Posted on • Updated on

Java Testing tools for 2024

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.
    @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);
    }
Enter fullscreen mode Exit fullscreen mode
  • Soft assertions. Collects all assertion errors instead of stopping at the first one.
    @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);
        });
    }
Enter fullscreen mode Exit fullscreen mode
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)
Enter fullscreen mode Exit fullscreen mode
  • Custom assertions. Create your own validation.
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();
    }
Enter fullscreen mode Exit fullscreen mode

Rest-Assured

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

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

        assertThat(personResponse.getName()).isEqualTo("John");
    }
Enter fullscreen mode Exit fullscreen mode

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
@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());
    ...
}
Enter fullscreen mode Exit fullscreen mode

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

Top comments (2)

Collapse
 
jagedn profile image
Jorge

Don't forget testcontainers, IMHO this is a must

Collapse
 
ivangavlik profile image
ivan.gavlik

yes you are right :) I guess we need one more post