package play.modules.springtester;

import java.util.HashMap;
import java.util.Map;

import org.junit.After;
import org.junit.Before;
import org.springframework.beans.factory.config.BeanDefinition;

/**
 * Used to test classes that require resources to be injected via spring plus the ability to inject mocked objects. Declare the test's subject by annotating a field with @Subject and this class will
 * resolve the subject and inject any mocks/real dependencies.  To declare a mock object to be injected, annotate a field with @Mock.
 * <p/>
 * Example injection of subject field: @Subject private MySubject subject;
 * <p/>
 * Example injection of mock field: @Mock(name = "optionalName") private Dependency mockDependency;
 * <p/>
 * The above will inject the mockDependency object into the optionalName field in the MySubject object.
 */
public abstract class SpringMockitoUnitTestCase extends DatabaseUnitTestCase {
    private final Map<String, BeanDefinition> definitions = new HashMap<String, BeanDefinition>();
    private final SpringMockitoMaster master = new SpringMockitoMaster();

    @Before
    public void injectMocksIntoSubject() throws IllegalAccessException {
        master.before(this, definitions);
    }

    @After
    public void revertMocksFromApplicationContext() {
        master.after(definitions);
    }

    /**
     * Register an object for the test.  This method is particularly useful to register a mock for just the one test but not for any of the others
     * in the test class.
     * @param name The name of the bean to be registered in spring's application context.
     * @param object The object to register against the name.
     */
    public void registerObject(String name, Object object) {
        master.registerBeanDefinition(name, object, definitions);
    }
}
