package org.ovirt.engine.ui.uicommonweb.junit;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.ovirt.engine.ui.frontend.Frontend;
import org.ovirt.engine.ui.uicommonweb.TypeResolver;
import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider;
import org.ovirt.engine.ui.uicommonweb.junit.UiCommonSetup.Mocks;
import org.ovirt.engine.ui.uicompat.ConstantsManager;
import org.ovirt.engine.ui.uicompat.Enums;
import org.ovirt.engine.ui.uicompat.UIConstants;
import org.ovirt.engine.ui.uicompat.UIMessages;
/**
* JUnit TestRule used to set up the necessary UiCommon infrastructure in order to test individual UiCommon models.
* <p>
* This TestRule ensures that hidden expectations of UiCommon models (represented by static method calls) are satisfied
* and provides an {@linkplain UiCommonSetup.Mocks interface} for stubbing the infrastructure behavior, if necessary.
* <p>
* Example usage - UiCommon infrastructure setup <b>per test class</b>:
*
* <pre>
* public class MyTest {
*
* @ClassRule
* public static UiCommonSetup setup = new UiCommonSetup();
*
* // This is optional, but often necessary
* @BeforeClass
* public static void stubUiCommonInfra() {
* AsyncDataProvider adp = setup.getMocks().asyncDataProvider();
* when(adp.isWindowsOsType(anyInt())).thenReturn(true);
* }
*
* // Actual test code to exercise model instance(s)
*
* }
* </pre>
*
* Example usage - UiCommon infrastructure setup <b>per test method</b>:
*
* <pre>
* public class MyTest {
*
* @Rule
* public UiCommonSetup setup = new UiCommonSetup();
*
* // This is optional, but often necessary
* @Before
* public void stubUiCommonInfra() {
* AsyncDataProvider adp = setup.getMocks().asyncDataProvider();
* when(adp.isWindowsOsType(anyInt())).thenReturn(true);
* }
*
* // Actual test code to exercise model instance(s)
*
* }
* </pre>
*/
public class UiCommonSetup implements TestRule {
/**
* Interface exposing UiCommon infrastructure components as mock objects.
*/
public interface Mocks {
AsyncDataProvider asyncDataProvider();
Frontend frontend();
TypeResolver typeResolver();
UIConstants uiConstants();
UIMessages uiMessages();
Enums enums();
}
private Env env;
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
env = new Env();
env.update(true);
base.evaluate();
env.update(false);
env = null;
}
};
}
public Mocks getMocks() {
if (env == null) {
throw new IllegalStateException("getMocks() is scoped to test rule execution context"); //$NON-NLS-1$
}
return env.mocks;
}
}
class Env {
private final AsyncDataProvider asyncDataProvider = mock(AsyncDataProvider.class);
private final Frontend frontend = mock(Frontend.class, RETURNS_DEEP_STUBS);
private final TypeResolver typeResolver = mock(TypeResolver.class);
private final ConstantsManager constantsManager = mock(ConstantsManager.class);
private final UIConstants uiConstants = mock(UIConstants.class);
private final UIMessages uiMessages = mock(UIMessages.class);
private final Enums enums = mock(Enums.class);
final Mocks mocks = new Mocks() {
@Override
public AsyncDataProvider asyncDataProvider() {
return asyncDataProvider;
}
@Override
public Frontend frontend() {
return frontend;
}
@Override
public TypeResolver typeResolver() {
return typeResolver;
}
@Override
public UIConstants uiConstants() {
return uiConstants;
}
@Override
public UIMessages uiMessages() {
return uiMessages;
}
@Override
public Enums enums() {
return enums;
}
};
Env() {
when(constantsManager.getConstants()).thenReturn(uiConstants);
when(constantsManager.getMessages()).thenReturn(uiMessages);
when(constantsManager.getEnums()).thenReturn(enums);
}
void update(boolean init) {
AsyncDataProvider.setInstance(init ? asyncDataProvider : null);
Frontend.setInstance(init ? frontend : null);
TypeResolver.setInstance(init ? typeResolver : null);
ConstantsManager.setInstance(init ? constantsManager : null);
}
}