package restx.factory.alternative;
import static org.assertj.core.api.Assertions.assertThat;
import static restx.factory.Factory.LocalMachines.overrideComponents;
import static restx.factory.Factory.LocalMachines.threadLocal;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import restx.factory.Factory;
import restx.factory.Name;
import restx.factory.alternative.components.TestAlternativesFromModule;
import restx.factory.alternative.components.TestComponentInterface;
import restx.factory.alternative.components.TestComponentNamed;
import restx.factory.alternative.components.TestComponentSimple;
import restx.factory.alternative.components.TestComponentsFromModule;
/**
* Test cases for alternatives.
*
* @author apeyrard
*/
public class AlternativeTest {
/**
* ElementsFromConfig component can not be build, because of module TestMandatoryDependency
* which use a missing dependency.
*/
@BeforeClass
public static void deactivateElementsFromConfig() {
System.setProperty("restx.activation::restx.factory.FactoryMachine::ElementsFromConfig", "false");
}
/**
* cleanup state before each test method
*/
@Before
public void cleanupBefore() {
threadLocal().clear();
}
/**
* cleanup state after this test class execution
*/
@AfterClass
public static void cleanupAfterClass() {
threadLocal().clear();
}
/*
This test uses the TestComponentSimple, and TestComponentSimpleAlternative. It uses the default alternative
mechanism without using Named annotation.
*/
@Test
public void should_use_alternative_for_basic_components() {
Factory factory = Factory.newInstance();
TestComponentSimple component = factory.getComponent(TestComponentSimple.class);
assertThat(component.greet()).isEqualTo("hello");
overrideComponents().set("restx.test.alternatives", "true");
factory = Factory.newInstance();
component = factory.getComponent(TestComponentSimple.class);
assertThat(component.greet()).isEqualTo("bonjour");
}
/*
This test uses the TestComponentNamed and TestComponentNamedAlternative, the alternative
should be registered under the name defined in the reference component
*/
@Test
public void should_use_alternative_for_named_components() {
Factory factory = Factory.newInstance();
TestComponentNamed component = factory.getComponent(Name.of(TestComponentNamed.class, "restx.test.component.speed"));
assertThat(component.speed()).isEqualTo("slow");
overrideComponents().set("restx.test.alternatives", "true");
factory = Factory.newInstance();
component = factory.getComponent(Name.of(TestComponentNamed.class, "restx.test.component.speed"));
assertThat(component.speed()).isEqualTo("fast");
}
/*
This test uses component based on an interface, the alternative reference the interface and force to be registered
with the same name as the original component.
*/
@Test
public void should_use_alternative_referencing_an_interface() {
Factory factory = Factory.newInstance();
TestComponentInterface component = factory.getComponent(Name.of(TestComponentInterface.class, "restx.test.component.name"));
assertThat(component.name()).isEqualTo("original");
overrideComponents().set("restx.test.alternatives", "true");
factory = Factory.newInstance();
component = factory.getComponent(Name.of(TestComponentInterface.class, "restx.test.component.name"));
assertThat(component.name()).isEqualTo("alternative");
}
/*
This test uses a component provided by a module, in order to create an alternative, it has to use the name of the
method annotated with @Provides.
*/
@Test
public void should_use_alternative_for_provided_component_using_the_method_as_name() {
Factory factory = Factory.newInstance();
TestComponentsFromModule.SomeInterface component = factory.getComponent(TestComponentsFromModule.SomeInterface.class);
assertThat(component.mode()).isEqualTo("production");
overrideComponents().set("restx.test.alternatives", "true");
factory = Factory.newInstance();
component = factory.getComponent(TestComponentsFromModule.SomeInterface.class);
assertThat(component.mode()).isEqualTo("dev");
}
/*
This test uses a named component provided by a module, in order to create an alternative, it has to use the same
name as the component.
*/
@Test
public void should_use_alternative_for_provided_named_component_using_same_name() {
Factory factory = Factory.newInstance();
TestComponentsFromModule.SomeOtherInterface component = factory.getComponent(
Name.of(TestComponentsFromModule.SomeOtherInterface.class, "restx.test.component.productionNamed"));
assertThat(component.mode()).isEqualTo("production");
overrideComponents().set("restx.test.alternatives", "true");
factory = Factory.newInstance();
component = factory.getComponent(Name.of(TestComponentsFromModule.SomeOtherInterface.class, "restx.test.component.productionNamed"));
assertThat(component.mode()).isEqualTo("dev");
}
/*
This test uses an alternative defined in a module.
*/
@Test
public void should_use_alternative_defined_in_modules() {
Factory factory = Factory.newInstance();
TestAlternativesFromModule.Calculation component = factory.getComponent(TestAlternativesFromModule.Calculation.class);
assertThat(component.calculate(2, 3)).isEqualTo(5);
overrideComponents().set("restx.test.alternatives", "true");
factory = Factory.newInstance();
component = factory.getComponent(TestAlternativesFromModule.Calculation.class);
assertThat(component.calculate(2, 3)).isEqualTo(6);
}
/*
This test uses an alternative defined in a module, and the referenced component use a Named annotation
*/
@Test
public void should_use_alternative_defined_in_modules_for_named_components() {
Factory factory = Factory.newInstance();
TestAlternativesFromModule.Flag component = factory.getComponent(TestAlternativesFromModule.Flag.class);
assertThat(component.value()).isEqualTo(true);
overrideComponents().set("restx.test.alternatives", "true");
factory = Factory.newInstance();
component = factory.getComponent(TestAlternativesFromModule.Flag.class);
assertThat(component.value()).isEqualTo(false);
}
/*
This test defines two alternatives, with different priorities, check that the higher is used.
*/
@Test
public void should_use_alternative_with_higher_priority() {
Factory factory = Factory.newInstance();
TestAlternativesFromModule.Priority component = factory.getComponent(TestAlternativesFromModule.Priority.class);
assertThat(component.value()).isEqualTo(Integer.MAX_VALUE);
overrideComponents().set("restx.test.alternatives", "true");
factory = Factory.newInstance();
component = factory.getComponent(TestAlternativesFromModule.Priority.class);
assertThat(component.value()).isEqualTo(Integer.MIN_VALUE);
}
}