to the tests. In a fluent way, you can assert: • Common types: Optional, Predicates, Streams, Iterable … • Primitive types • Java 8 Temporal Types • Atomic Types
recursiveComparisonTest() { var simulation1 = Simulation.builder().name("John").cpf("9582728395") .email("[email protected]").amount(new BigDecimal("500")).installments(1) .insurance(false).build(); var simulation2 = SimulationDto.builder().name("John").cpf("9582728395") .email("[email protected]").amount(new BigDecimal("500")).installments(1) .insurance(false).build(); // ✅ won't fail because the assertion is done field by field assertThat(simulation1).usingRecursiveComparison().isEqualTo(simulation2); // ❌ will fail because equals compare references assertThat(simulation1).isEqualTo(simulation2); }
var simulation = Simulation.builder().name("John").cpf("9582728395") .email("[email protected]").amount(new BigDecimal("500")) .installments(1).insurance(false).build(); SimulationAssert.assertThat(simulation).hasValidInstallments(); SimulationAssert.assertThat(simulation).hasValidAmount(); // never gets here }
Soft Assertion Custom Assertion • Custom assertion methods based on a context (Simulation) Scalable one • Custom Soft Assertion using the the Custom Assertion
a DSL to simplify testing of REST based services based on the given-when-then keywords (but it’s not BDD). class RestAssuredExampleTest { @Test void welcome() { given() .param("name", "Elias"). when() .post("/register"). then() .statusCode(200) .body("message", is("")); } }
wait for an asynchronous system (RabbitMQ, Apache Kafka, Redis, and others) to complete the request. It has the ability to: • create conditions to wait • check fields • support Atomic structures • ignoring and checking exceptions • integrate with AssertJ
some time to complete and there’s no indication of waiting for something to happen. @Test void checkEventWithRestriction() { String cpf = "26276298085"; checkForRestriction(cpf); given().pathParam("cpf", cpf).when().get("/events/{cpf}").then().statusCode(SC_OK); }
query, to check for the data, and then continue the code execution. @Test void checkEventWithRestriction_Success() { String cpf = "55856777050"; checkForRestriction(cpf); await().atMost(10, SECONDS).until(eventIsFound(cpf)); given().pathParam("cpf", cpf).when().get("/events/{cpf}").then().statusCode(SC_OK); } // 👇 the Callable will do the trick public Callable<Boolean> eventIsFound(String cpf) { return () -> eventRepository.findByCpf(cpf).isPresent(); }
insertion • Use the event-source branch • Start the application • Login to H2 (sa/password) • Run a query into the EVENT_SOURCE table • Make a POST request (you can use the Swagger UI) • Run a query into the EVENT_SOURCE table • The insertion will occur only 7 seconds after the request
the checkEventWithRestriction_Fail() and see it failing because of the 7 second delay • Run the checkEventWithRestriction_Success() and see the test green Disclaimer There’s no asynchronous system here. A delay of 7 seconds was added in the EventService that will be called by the RestrictionController methods and SimulationsController for the POST and DELETE methods.
API mock testing. You probably know it by the isolated usage in your unit tests, like this: @WireMockTest public class WiremockTest { @Test void testUsingWiremock() { String response = """ { "error": "The cpf 987654321 as a restriction" } """; stubFor((get(urlEqualTo("/restriction")) .withQueryParam("cpf", equalTo("987654321")) .willReturn( aResponse().withResponseBody(response)))); } }
duplicated across the teams, you can implement a Service Virtualization approach using WireMock to share the same mock across multiple teams. Team 1 Team 2 Team N Service Virtualization Standalone local container Deploy in a k8s infra
faults in your code based on a series of mutants (specific code changes) showing you if your code has lived or killed mutations. • Lived mutations: indicates you have something to work on :) • Killed mutations: means that the change applied is covered
measures only the executed code. It adds the support of fault detections which are conditions we haven't added in the tests, mostly corner cases. There're a lot of mutators, and the most common ones are: • Conditional Boundary • Increment • Math