package org.camunda.bpm.extension.mockito.answer; import javax.annotation.Nonnull; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; /** * A fluent answer always returns the mock instance itself for all methods that * have the same return type as the mock instance. This makes it possible to * easily mock fluent-api behaviour without chaining the when/then stubbings or * relying on deep stubs. * * @param <T> * the return type of the answer */ public final class FluentAnswer<T> implements Answer<T> { /** * Creates a new mock of given type with a fluent default answer already set * up. * * @param type * type of mock * @param <T> * generic parameter for type of mock * @return new mock instance of type T with default fluent answer. */ public static <T> T createMock(Class<T> type) { return Mockito.mock(type, createAnswer(type)); } /** * Creates a new instance for the given type. * * @param type * the return type of the answer * @param <T> * generic parameter of the return type * @return new Answer that returns the mock itself */ public static <T> FluentAnswer<T> createAnswer(Class<T> type) { return new FluentAnswer<T>(type); } /** * Holds the internal type. */ private final Class<T> type; /** * Private constructor, use static factory methods to create. * * @param type * the type of the return value for the answer */ private FluentAnswer(Class<T> type) { this.type = type; } /** * Returns the mock itself if return type and mock type match (assume fluent * api). * * @param invocation * the method invocation. If its return type equals the mock type, * just return the mock. * @return the mock itself or null (meaning further stubbing is required). * @throws Throwable * when anything fails */ @Override public T answer(@Nonnull final InvocationOnMock invocation) throws Throwable { if (invocation.getMethod().getReturnType().isAssignableFrom(type)) { return (T) invocation.getMock(); } return null; } }