package org.ovirt.engine.core.utils;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.ovirt.engine.core.common.businessentities.VdcOption;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigCommon;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.config.IConfigUtilsInterface;
import org.ovirt.engine.core.compat.Version;
/**
* This rule is used to mock {@link Config} values in an easy fashion, without having to resort to Power Mocking.
*
* To use it, simple add a {@link MockConfigRule} member to your test, with the {@link org.junit.Rule} annotation.
* Mocking is done by calling {@link #mockConfigValue(ConfigValues, Object)} or {@link #mockConfigValue(ConfigValues, String, Object)} with the value you need.
*/
public class MockConfigRule extends TestWatcher {
private static final Answer<?> DEFAULT_CONF_ANSWER = invocationOnMock -> {
Method invokedMethod = invocationOnMock.getMethod();
if (invokedMethod.getName().equals("getValue") && invokedMethod.getParameterCount() == 2) {
VdcOption option = new VdcOption();
option.setOptionName(((ConfigValues) invocationOnMock.getArguments()[0]).name());
option.setVersion((String) invocationOnMock.getArguments()[1]);
return ((ConfigUtilsBase) invocationOnMock.getMock()).getValue(option);
}
return invocationOnMock.callRealMethod();
};
private static final ConfigUtilsBase MOCK_CONFIG_UTILS = mock(ConfigUtilsBase.class, DEFAULT_CONF_ANSWER);
/** A descriptor for a single config mocking */
public static class MockConfigDescriptor<T> {
public MockConfigDescriptor(ConfigValues value, String version, T returnValue) {
this.value = value;
this.version = version;
this.returnValue = returnValue;
}
public ConfigValues getValue() {
return value;
}
public String getVersion() {
return version;
}
public T getReturnValue() {
return returnValue;
}
private ConfigValues value;
private String version;
private T returnValue;
}
private IConfigUtilsInterface origConfUtils;
private List<MockConfigDescriptor<?>> configs;
/** Create the rule, mocking the given configurations */
public <T> MockConfigRule(MockConfigDescriptor<?>... configs) {
this(Arrays.asList(configs));
}
/** Create the rule, mocking the given configurations */
public <T> MockConfigRule(List<MockConfigDescriptor<?>> configs) {
this.configs = new ArrayList<>(configs);
}
/** Mock the configuration of a single value - this can be given as an argument to the rule's constructor */
public static <T> MockConfigDescriptor<T> mockConfig(ConfigValues value, String version, T returnValue) {
return new MockConfigDescriptor<>(value, version, returnValue);
}
public static <T> MockConfigDescriptor<T> mockConfig(ConfigValues value, Version version, T returnValue) {
return new MockConfigDescriptor<>(value, version.toString(), returnValue);
}
/** Mock the default version configuration of a single value - this can be given as an argument to the rule's constructor */
public static <T> MockConfigDescriptor<T> mockConfig(ConfigValues value, T returnValue) {
return new MockConfigDescriptor<>(value, ConfigCommon.defaultConfigurationVersion, returnValue);
}
public <T> void mockConfigValue(ConfigValues value, T returnValue) {
mockConfigValue(value, ConfigCommon.defaultConfigurationVersion, returnValue);
}
public <T> void mockConfigValue(ConfigValues value, Version version, T returnValue) {
mockConfigValue(value, version.getValue(), returnValue);
}
public <T> void mockConfigValue(MockConfigDescriptor<T> mcd) {
mockConfigValue(mcd.getValue(), mcd.getVersion(), mcd.getReturnValue());
}
private static <T> void mockConfigValue(ConfigValues value, String version, T returnValue) {
doReturn(returnValue).when(Config.getConfigUtils()).getValue(value, version);
}
@Override
public void starting(Description description) {
origConfUtils = Config.getConfigUtils();
Config.setConfigUtils(MOCK_CONFIG_UTILS);
for (MockConfigDescriptor<?> config : configs) {
mockConfigValue(config.getValue(), config.getVersion(), config.getReturnValue());
}
}
@Override
public void finished(Description description) {
Mockito.reset(MOCK_CONFIG_UTILS);
Config.setConfigUtils(origConfUtils);
}
}