/* * Copyright 2014 Avanza Bank AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.avanza.astrix.test; import com.avanza.astrix.config.GlobalConfigSourceRegistry; import com.avanza.astrix.config.Setting; import com.avanza.astrix.context.Astrix; import com.avanza.astrix.context.AstrixContext; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; import java.util.function.Consumer; /** * Test utility that manages an internal service registry, config-source and AstrixContext. The * managed AstrixContext is configured to use the internal service registry.<p> * * The AstrixRule allows registering providers programmatically in the * service-registry, see {@link AstrixRule#setProxyState(Class, Object)}. * * Typical usage: <p> * * <pre> * * {@literal @}ClassRule * public static AstrixRule astrix = new AstrixRule(); * * {@literal @}ClassRule * public static RunningPu testedPu = ... // setup pu * * * {@literal @}Test * public void aTest() { * ... * astrix.registerProvider(ConsumedService.class, serviceStub); * ... * ServiceUnderTest service = astrix.waitForBean(ServiceUnderTest.class, 2000); * } * * {@literal @}Test * public void anotherTest() { * ... * astrix.registerProvider(ConsumedService.class, serviceStubWithDifferentBehavior); * ... * ServiceUnderTest service = astrix.waitForBean(ServiceUnderTest.class, 2000); * } * * </pre> * * * @author Elias Lindholm * */ public class AstrixRule implements TestRule { private final AstrixTestContext astrixTestContext; public AstrixRule(Class<?>... testApis) { this.astrixTestContext = new AstrixTestContext(testApis); } public AstrixRule(Consumer<AstrixRuleContext> contextConfigurer, Class<?>... testApis) { this(testApis); contextConfigurer.accept(new AstrixRuleContext() { @Override public <T> void registerProxy(Class<T> service) { astrixTestContext.registerProxy(service); } @Override public <T> void registerProxy(Class<T> service, String qualifier) { astrixTestContext.registerProxy(service, qualifier); } @Override public <T> void set(Setting<T> setting, T value) { astrixTestContext.set(setting, value); } }); } @Override public Statement apply(final Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { try { base.evaluate(); } finally { try { astrixTestContext.destroy(); } catch (Exception e) { e.printStackTrace(); } } } }; } /** * The configSourceId might be used to retrieve the ConfigSource instance * using {@link GlobalConfigSourceRegistry#getConfigSource(String)} * * @return the configSourceId for the associated ConfigSource. */ public String getConfigSourceId() { return astrixTestContext.getConfigSourceId(); } /** * @return the serviceUri for the associated service-registry. */ public String getServiceRegistryUri() { return astrixTestContext.getServiceRegistryUri(); } public void destroy() { this.astrixTestContext.destroy(); } /** * @see AstrixRuleContext#registerProxy(Class) * * @param service - The qualified bean type to register a proxy for */ public <T> void registerProxy(Class<T> service) { astrixTestContext.registerProxy(service); } /** * @see AstrixRuleContext#registerProxy(Class) * * @param service - The qualified bean type to register a proxy for * @param qualifier - The qualifier of the bean type to register a proxy for */ public <T> void registerProxy(Class<T> service, String qualifier) { astrixTestContext.registerProxy(service, qualifier); } /** * Sets the proxy state for a given proxy in the service registry. If no proxy has bean registered * before it will be created with the given initial state, * see {@link AstrixRuleContext#registerProxy(Class)} for more details. * * When a service-provider is proxied it allows fast switching of the given provider between * different test-runs, without restarting the entire test environment. * * @param type - The api to register a provider for. * @param mock - The instance to delegate all invocations to the given api to. Might be null in which case a ServiceUnavailableException will be thrown when the service is invoked. */ public <T> void setProxyState(final Class<T> type, final T mock) { astrixTestContext.setProxyState(type, mock); } /** * Sets the proxy state for a given proxy in the service registry. If no proxy has bean registered * before it will be created with the given initial state, * see {@link AstrixRuleContext#registerProxy(Class)} for more details. * * When a service-provider is proxied it allows fast switching of the given provider between * different test-runs, without restarting the entire test environment. * * @param type - The api to register a provider for. * @param qualifier - The qualifier for the service bean to register a provider for * @param mock - The instance to delegate all invocations to the given api to. Might be null in which case a ServiceUnavailableException will be thrown when the service is invoked. * */ public <T> void setProxyState(final Class<T> type, final String qualifier, final T mock) { astrixTestContext.setProxyState(type, qualifier, mock); } public void resetProxies() { astrixTestContext.resetProxies(); } public <T> T waitForBean(Class<T> type, long timeoutMillis) throws InterruptedException { return astrixTestContext.waitForBean(type, timeoutMillis); } public <T> T waitForBean(Class<T> type, String qualifier, long timeoutMillis) throws InterruptedException { return astrixTestContext.waitForBean(type, qualifier, timeoutMillis); } public Astrix getAstrix() { return astrixTestContext.getAstrixContext(); } public AstrixContext getAstrixContext() { return astrixTestContext.getAstrixContext(); } public <T extends TestApi> T getTestApi(Class<T> testApi) { return astrixTestContext.getTestApi(testApi); } void resetTestApis() { this.astrixTestContext.resetTestApis(); } <T> T getBean(Class<T> serviceBean) { return astrixTestContext.getBean(serviceBean); } <T> T getBean(Class<T> serviceBean, String qualifier) { return astrixTestContext.getBean(serviceBean, qualifier); } public void setConfigurationProperty(String settingName, String value) { astrixTestContext.setConfigurationProperty(settingName, value); } }