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

io.github.theangrydev.fluentbdd.mockito.FluentMockito Maven / Gradle / Ivy

There is a newer version: 8.2.2
Show newest version
/*
 * Copyright 2016 Liam Williams .
 *
 * This file is part of fluent-bdd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.github.theangrydev.fluentbdd.mockito;

import io.github.theangrydev.fluentbdd.core.FluentBdd;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.mockito.BDDMockito;
import org.mockito.InOrder;
import org.mockito.Mockito;
import org.mockito.MockitoFramework;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.listeners.MockCreationListener;
import org.mockito.mock.MockCreationSettings;

import java.util.HashSet;
import java.util.Set;

//TODO: document
public class FluentMockito implements MethodRule, FluentMockitoCommands, MockCreationListener {

    private final MockitoFramework mockitoFramework;
    private final MockitoRule mockitoRule;

    private final FluentBdd fluentBdd;

    private final Set mocks = new HashSet<>();

    private InOrder inOrder;

    public FluentMockito(FluentBdd fluentBdd) {
        this(Mockito.framework(), MockitoJUnit.rule(), fluentBdd);
    }

    // Only visible for testing to inject MockitoFramework and MockitoRule
    FluentMockito(MockitoFramework mockitoFramework, MockitoRule mockitoRule, FluentBdd fluentBdd) {
        this.mockitoRule = mockitoRule;
        this.fluentBdd = fluentBdd;
        this.mockitoFramework = mockitoFramework;
        mockitoFramework.addListener(this);
    }

    //TODO: look into ThreadSafeMockingProgress to see if that can improve this API?
    //TODO: talk to the verification here to make sure the FluentMockitoGiven is not reused
    @Override
    public  FluentMockitoGiven given(Mock mock) {
        FluentMockitoGiven given = new FluentMockitoGiven<>(mock);
        fluentBdd.verification.recordGiven(given);
        return given;
    }

    @Override
    public  Mock thenVerify(Mock mock) {
        return fluentBdd().then(testResult -> {
            return verify(mock);
        });
    }

    private  Mock verify(Mock mock) {
        if (inOrder == null) {
            inOrder = BDDMockito.inOrder(mocks.toArray());
        }
        return inOrder.verify(mock);
    }

    @Override
    public FluentBdd fluentBdd() {
        return fluentBdd;
    }

    @Override
    public Statement apply(Statement base, FrameworkMethod method, Object target) {
        try {
            return mockitoRule.apply(base, method, target);
        } finally {
            mockitoFramework.removeListener(this);
        }
    }

    @Override
    public void onMockCreated(Object mock, MockCreationSettings settings) {
        mocks.add(mock);
    }
}