Basil Bourque
Basil Bourque

Reputation: 338306

Practical uses for the option to pass `Supplier` as a message supplier in JUnit 5

The Assertions class in JUnit 5 allows for passing an Supplier<String> as a messageSupplier, an object that provides the text of a message to report when the test fails.

For example, assertEquals:

public static void assertEquals​( char expected,
                                 char actual,
                                 Supplier<String> messageSupplier )

I am wondering what the practical use of such a supplier might be, specifically in the context of unit testing.

I can imagine perhaps localizing the strings, though that seems a bit strange to localize when the audience is the members of a development project.

➥ Are there any other practical uses of passing such a message supplier rather than hard-coding message string?

Upvotes: 9

Views: 3207

Answers (2)

lorenzo-bettini
lorenzo-bettini

Reputation: 2635

When the message can be built only in case of failure

Besides being useful when building the message is expensive, as already answered, I think another interesting and useful use-case is when the failure message can be constructed only in case of failure.

For example, let's say that you have an object as a result of one of your methods, and you expect that object to be null. In case of failure you want to show a failure message with some information taken from the unexpected non-null object, e.g., by calling one of its methods:

MyEntity e = mySut.find(...);
assertNull(e, "Unexpected found entity with id: " + e.getId());

This test method will always throw a NullPointerException when the test should succeed. In fact, the message string is always evaluated, being an argument of the assert method. Instead of resorting to a more complex and involved solution, undermining the readability of your tests, like

MyEntity e = mySut.find(...);
String failureMessage = "";
if (e != null)
   failureMessage = "Unexpected found entity with id: " + e.getId();
assertNull(e, failureMessage);

You can simply use the assert method with a message supplier:

MyEntity e = mySut.find(...);
assertNull(e, () -> "Unexpected found entity with id: " + e.getId());

Now, the body of the lambda will be executed only in case of failure, when the object used to create the message is surely not null.

Upvotes: 11

johanneslink
johanneslink

Reputation: 5341

When building message is expensive

If I remember correctly, we - the JUnit 5 team - introduced the supplier variant for cases in which building the message string is costly, eg due to accessing a database. You’d only want to do this if necessary, ie in case of failure.

Upvotes: 11

Related Questions