[JAVA] Be able to write Hamcrest Matchers in lambda expressions

If you are implementing Java testing with JUnit + Hamcrest, you may want to implement the second argument of the assertThat method in a lambda expression. However, since the type of the second argument of assertThat is org.hamcrest.Matcher, it does not correspond to Java 8 lambda expressions. (Because Hamcrest 2.1 is built with Java 7)

I thought about how to implement value validation with a lambda expression.

Test implementation image

The following program is a test to check if the method to be verified is 0 or less. Matcher when it is smaller than the specified value is provided by hamcrest, but here it is just a sample ...

@Test
public void testSum() {
 // Test if the value is less than or equal to 0
    assertThat(new App().sum(10, -20), is(matches(i -> i <= 0, "negative value")));
}

Effective usage

--When there are several comparison conditions. For example, verifying whether it matches any of 1,2,3,4, etc. --If you want to implement property comparison in an object with a method other than the equals method --The verification method is simple, but when there are a large number of classes of objects to verify. When creating a custom Matcher class for each object is expected to take too much effort.

Realization method

Implement a custom Matcher like the one below. You can implement code like the one above by statically importing that custom Matcher.

import java.util.function.Predicate;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

public class LambdaMatcher<T> extends TypeSafeMatcher<T> {

	private Predicate<T> predicate;
	private String message;

	public LambdaMatcher(Predicate<T> predicate, String message) {
		this.predicate = predicate;
		this.message = message;
	}

	@Override
	public void describeTo(Description description) {
		description.appendText(this.message);
	}

	@Override
	protected boolean matchesSafely(T item) {
		return this.predicate.test(item);
	}

	public static <T> Matcher<T> matches(Predicate<T> predicate, String message) {
		return new LambdaMatcher<>(predicate, message);
	}
}

In addition, although the method is to receive the message from the caller as a String type, it can also be used like the Assertions class of JUnit5 by using the Supplier \ <String > type.

I hope it helps if you want to test with a lambda expression in Hamcrest.

Remarks

--2018/12/31 Since it was pointed out in the comment, the code of the implementation method was corrected. Thank you very much.

Recommended Posts

Be able to write Hamcrest Matchers in lambda expressions
I want to be able to think and write regular expressions myself. ..
[Java] Introduction to lambda expressions
[Introduction to Java] About lambda expressions
[Rails] How to write in Japanese
Things to note in conditional expressions
How to use Java lambda expressions
I tried to summarize Java lambda expressions
To write Response data directly in Spring
[Ruby] Basic key to be strong in refactoring
[Rails] Various ways to write in seed files
JUnit 5: How to write test cases in enum
There seems to be no else-if in java
I want to be eventually even in kotlin
Site summary to be helpful in Minecraft modding 1.12.2
How to write Java String # getBytes in Kotlin?
Notes on how to write comments in English
Pass the condition to be used in the Java8 lambda expression filter () as a parameter