package com.atlassian.bitbucket.mesh.test.context;

import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.exceptions.base.MockitoException;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;

import javax.annotation.Nonnull;

/**
 * Simulates the work of running a unit test with Mockito's {@code MockitoJUnitRunner}, initialising any fields
 * which are annotated with {@code Mock}.
 */
public class MockitoTestExecutionListener extends AbstractTestExecutionListener {

    private AutoCloseable mocks;

    @Override
    public void afterTestMethod(@Nonnull TestContext testContext) {
        try {
            mocks.close();
        } catch (Exception e) {
            throw new MockitoException("Failed to release mocks!", e);
        }
        Mockito.validateMockitoUsage();
    }

    @Override
    public int getOrder() {
        return 2500; //Between DependencyInjectionTestExecutionListener and DirtiesContextTestExecutionListener
    }

    @Override
    public void prepareTestInstance(@Nonnull TestContext testContext) {
        mocks = MockitoAnnotations.openMocks(testContext.getTestInstance());
    }
}
