All Downloads are FREE. Search and download functionalities are using the official Maven repository.

info.solidsoft.mockito.java8.LambdaMatcher Maven / Gradle / Ivy

/*
 * Copyright (C) 2015 Marcin Zajączkowski.
 *
 * Licensed under the Apache License, Version 2.0.
 */
package info.solidsoft.mockito.java8;

import org.mockito.ArgumentMatcher;

import java.util.function.Predicate;

import static org.mockito.ArgumentMatchers.argThat;

/**
 * Allows creating inlined argument matcher with a lambda expression.
 * 

* With Java 8 and lambda expressions ArgumentCaptor can be expressed inline: * *


 *{@literal @}Test
 * public void shouldAllowToUseLambdaInStubbing() {
 *     //given
 *     given(ts.findNumberOfShipsInRangeByCriteria(argLambda(c -> c.getMinimumRange() > 1000))).willReturn(4);
 *     //expect
 *     assertThat(ts.findNumberOfShipsInRangeByCriteria(new ShipSearchCriteria(1500, 2))).isEqualTo(4);
 *     //expect
 *     assertThat(ts.findNumberOfShipsInRangeByCriteria(new ShipSearchCriteria(700, 2))).isEqualTo(0);
 * }
 * 
*

* In comparison the same logic implemented with a custom Answer in Java 7: * *


 *{@literal @}Test
 * public void stubbingWithCustomAsnwerShouldBeLonger() {  //old way
 *     //given
 *     given(ts.findNumberOfShipsInRangeByCriteria(any())).willAnswer(new Answer() {
 *        {@literal @}Override
 *         public Integer answer(InvocationOnMock invocation) throws Throwable {
 *             Object[] args = invocation.getArguments();
 *             ShipSearchCriteria criteria = (ShipSearchCriteria) args[0];
 *             if (criteria.getMinimumRange() > 1000) {
 *                 return 4;
 *             } else {
 *                 return 0;
 *             }
 *         }
 *     });
 *     //expect
 *     assertThat(ts.findNumberOfShipsInRangeByCriteria(new ShipSearchCriteria(1500, 2))).isEqualTo(4);
 *     //expect
 *     assertThat(ts.findNumberOfShipsInRangeByCriteria(new ShipSearchCriteria(700, 2))).isEqualTo(0);
 * }
 * 
*

* Even Java 8 alone and using less readable constructions produce less compact code: * *


 *{@literal @}Test
 * public void stubbingWithCustomAsnwerShouldBeLongerEvenAsLambda() {  //old way
 *     //given
 *     given(ts.findNumberOfShipsInRangeByCriteria(any())).willAnswer(invocation -> {
 *         ShipSearchCriteria criteria = (ShipSearchCriteria) invocation.getArguments()[0];
 *         return criteria.getMinimumRange() > 1000 ? 4 : 0;
 *     });
 *     //expect
 *     assertThat(ts.findNumberOfShipsInRangeByCriteria(new ShipSearchCriteria(1500, 2))).isEqualTo(4);
 *     //expect
 *     assertThat(ts.findNumberOfShipsInRangeByCriteria(new ShipSearchCriteria(700, 2))).isEqualTo(0);
 * }
 * 
* * @param type of argument * * @author Marcin Zajączkowski */ public class LambdaMatcher implements ArgumentMatcher { private final ArgumentMatcher backendMatcher; //TODO: Could it be done with just one matcher? private LambdaMatcher(Predicate lambda, String description) { this.backendMatcher = new ArgumentMatcher() { @SuppressWarnings("unchecked") @Override public boolean matches(Object item) { try { return lambda.test((T)item); } catch (Exception e) { throw new RuntimeException(e); } } @Override public String toString() { return description; } }; } @Override public boolean matches(T item) { return backendMatcher.matches(item); } @Override public String toString() { return backendMatcher.toString(); } public static T argLambda(Predicate lambda) { return argLambda(lambda, "Inline lambda expression - add description in code to get more detailed error message"); } public static T argLambda(Predicate lambda, String description) { return argThat(new LambdaMatcher<>(lambda, description)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy