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

guru.mocker.java.api.MockerBase Maven / Gradle / Ivy

The newest version!
package guru.mocker.java.api;

import guru.mocker.java.api.annotation.UseCase;
import guru.mocker.java.internal.CallableMethod;
import guru.mocker.java.internal.api.DefaultMockerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Optional;
import java.util.concurrent.Callable;

import static guru.mocker.java.api.util.TestFrameworkUtil.unWrapArguments;

public class MockerBase implements GivenMocker
{
    private final MockerContext mockerContext;

    public MockerBase()
    {
        this(new DefaultMockerFactory());
    }

    protected MockerBase(MockerFactory mockerFactory)
    {
        mockerContext = mockerFactory.createMockerContext();

    }

    public void addAssert(Runnable... runnables)
    {
        mockerContext.asserts().addAll(Arrays.asList(runnables));
    }

    public void addMethods(Runnable mockRunnable, Runnable realRunnable)
    {
        addMethods(convertRunnableToCallable(mockRunnable), convertRunnableToCallable(realRunnable));
    }

    public void addMethods(Callable mockMethod, Callable realMethod)
    {
        mockerContext.methods().add(new CallableMethod<>(mockMethod, realMethod));
    }

    private Callable convertRunnableToCallable(Runnable runnable)
    {
        return () -> {
            runnable.run();
            return null;
        };
    }

    @Override
    public WhenMocker givenUseCase(String testCaseName, Object... arguments)
            throws Exception
    {
        Method testCaseMethod = findUseCaseMethod(testCaseName);

        callTestCaseMethod(testCaseMethod, arguments);
        return mockerContext.mockerFactory().createWhenMocker(mockerContext);
    }

    private Method findUseCaseMethod(String useCase)
    {
        Method[] methods = getClass().getMethods();
        Optional result = Arrays.stream(methods)
                .filter(method -> method.isAnnotationPresent(UseCase.class))
                .filter(method -> useCase.equals(method.getAnnotation(UseCase.class).value()))
                .findFirst();

        return result.orElseThrow(() -> new AssertionError("Unable to find method annotated as a given use case for '" + useCase + "'." +
                "\n Apply the annotation as @UseCase(\"" + useCase + "\") to the appropriate mocker method in " + getClass() + "."));
    }

    private void callTestCaseMethod(Method useCaseMethod, Object[] arguments)
            throws IllegalAccessException, InvocationTargetException
    {
        useCaseMethod.invoke(this, unWrapArguments(arguments));
    }

    public void addRealGivens(Runnable... runnable)
    {
        mockerContext.realGivens().addAll(Arrays.asList(runnable));
    }
}