make use of TestExceutionListener, remove static access to context (#551)

Signed-off-by: Michael Hirsch <michael.hirsch@bosch-si.com>
This commit is contained in:
Michael Hirsch
2017-06-30 08:38:06 +02:00
committed by Kai Zimmermann
parent ce31fbaa85
commit 589f9156ea
8 changed files with 65 additions and 126 deletions

View File

@@ -23,13 +23,9 @@ import org.eclipse.hawkbit.cache.DownloadIdCache;
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
import org.eclipse.hawkbit.event.BusProtoStuffMessageConverter;
import org.eclipse.hawkbit.repository.RolloutStatusCache;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver;
import org.eclipse.hawkbit.repository.test.util.JpaTestRepositoryManagement;
import org.eclipse.hawkbit.repository.test.util.TestContextProvider;
import org.eclipse.hawkbit.repository.test.util.TestRepositoryManagement;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
@@ -48,7 +44,6 @@ import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.cloud.bus.ConditionalOnBusEnabled;
import org.springframework.cloud.bus.ServiceMatcher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -106,12 +101,6 @@ public class TestConfiguration implements AsyncConfigurer {
return new ArtifactFilesystemRepository(artifactFilesystemProperties);
}
@Bean
public TestRepositoryManagement testRepositoryManagement(final SystemSecurityContext systemSecurityContext,
final SystemManagement systemManagement) {
return new JpaTestRepositoryManagement(cacheManager(), systemSecurityContext, systemManagement);
}
@Bean
public TestdataFactory testdataFactory() {
return new TestdataFactory();
@@ -202,14 +191,4 @@ public class TestConfiguration implements AsyncConfigurer {
public MessageConverter busProtoBufConverter() {
return new BusProtoStuffMessageConverter();
}
/**
* {@link TestContextProvider} bean.
*
* @return a new {@link TestContextProvider}
*/
@Bean
public ApplicationContextAware applicationContextProvider() {
return new TestContextProvider();
}
}

View File

@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.test.matcher;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.equalTo;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Optional;
import java.util.Set;
@@ -22,17 +23,15 @@ import java.util.stream.Stream;
import org.eclipse.hawkbit.repository.event.remote.RemoteIdEvent;
import org.eclipse.hawkbit.repository.event.remote.RemoteTenantAwareEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.repository.test.util.TestContextProvider;
import org.junit.Assert;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.bus.event.RemoteApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
import com.google.common.collect.ConcurrentHashMultiset;
import com.google.common.collect.Multiset;
@@ -43,35 +42,34 @@ import com.jayway.awaitility.core.ConditionTimeoutException;
/**
* Test rule to setup and verify the event count for a method.
*/
public class EventVerifier implements TestRule {
public class EventVerifier extends AbstractTestExecutionListener {
private static final Logger LOGGER = LoggerFactory.getLogger(EventVerifier.class);
private EventCaptor eventCaptor;
@Override
public Statement apply(final Statement test, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
final Optional<Expect[]> expectedEvents = getExpectationsFrom(description);
expectedEvents.ifPresent(events -> beforeTest());
try {
test.evaluate();
expectedEvents.ifPresent(events -> afterTest(events));
} finally {
expectedEvents.ifPresent(listener -> removeEventListener());
}
}
};
public void beforeTestMethod(final TestContext testContext) throws Exception {
final Optional<Expect[]> expectedEvents = getExpectationsFrom(testContext.getTestMethod());
expectedEvents.ifPresent(events -> beforeTest(testContext));
}
private Optional<Expect[]> getExpectationsFrom(final Description description) {
return Optional.ofNullable(description.getAnnotation(ExpectEvents.class)).map(ExpectEvents::value);
@Override
public void afterTestMethod(final TestContext testContext) throws Exception {
final Optional<Expect[]> expectedEvents = getExpectationsFrom(testContext.getTestMethod());
try {
expectedEvents.ifPresent(events -> afterTest(events));
} finally {
expectedEvents.ifPresent(listener -> removeEventListener(testContext));
}
}
private void beforeTest() {
final ConfigurableApplicationContext context = TestContextProvider.getContext();
private Optional<Expect[]> getExpectationsFrom(final Method testMethod) {
return Optional.ofNullable(testMethod.getAnnotation(ExpectEvents.class)).map(ExpectEvents::value);
}
private void beforeTest(final TestContext testContext) {
final ConfigurableApplicationContext context = (ConfigurableApplicationContext) testContext
.getApplicationContext();
eventCaptor = new EventCaptor();
context.addApplicationListener(eventCaptor);
}
@@ -111,8 +109,8 @@ public class EventVerifier implements TestRule {
}
private void removeEventListener() {
final ApplicationEventMulticaster multicaster = TestContextProvider.getContext()
private void removeEventListener(final TestContext testContext) {
final ApplicationEventMulticaster multicaster = testContext.getApplicationContext()
.getBean(ApplicationEventMulticaster.class);
multicaster.removeApplicationListener(eventCaptor);
}

View File

@@ -10,7 +10,6 @@ package org.eclipse.hawkbit.repository.test.util;
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE;
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE;
import static org.junit.rules.RuleChain.outerRule;
import java.io.File;
import java.io.IOException;
@@ -61,7 +60,6 @@ import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.rules.RuleChain;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
@@ -82,6 +80,8 @@ import org.springframework.hateoas.MediaTypes;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.TestExecutionListeners.MergeMode;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
@@ -99,6 +99,11 @@ import org.springframework.web.context.WebApplicationContext;
// refreshed we e.g. get two instances of CacheManager which leads to very
// strange test failures.
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
// Cleaning repository will fire "delete" events. We won't count them to the
// test execution. So, the order execution between EventVerifier and Cleanup is
// important!
@TestExecutionListeners(inheritListeners = true, listeners = { EventVerifier.class,
CleanupTestExecutionListener.class }, mergeMode = MergeMode.MERGE_WITH_DEFAULTS)
public abstract class AbstractIntegrationTest implements EnvironmentAware {
private static final Logger LOG = LoggerFactory.getLogger(AbstractIntegrationTest.class);
@@ -201,11 +206,6 @@ public abstract class AbstractIntegrationTest implements EnvironmentAware {
@Autowired
protected ServiceMatcher serviceMatcher;
@Rule
// Cleaning repository will fire "delete" events. We won't count them to the
// test execution. So there is order between both rules:
public RuleChain ruleChain = outerRule(new CleanRepositoryRule()).around(new EventVerifier());
@Rule
public final WithSpringAuthorityRule securityRule = new WithSpringAuthorityRule();

View File

@@ -1,21 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.test.util;
import org.junit.rules.ExternalResource;
public class CleanRepositoryRule extends ExternalResource {
@Override
protected void after() {
final TestRepositoryManagement repository = TestContextProvider.getContext()
.getBean(TestRepositoryManagement.class);
repository.clearTestRepository();
}
}

View File

@@ -0,0 +1,33 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.test.util;
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListener;
import org.springframework.test.context.support.AbstractTestExecutionListener;
/**
* A spring {@link TestExecutionListener} which cleansup the repository after
* each test-method.
*/
public class CleanupTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void afterTestMethod(final TestContext testContext) throws Exception {
final ApplicationContext applicationContext = testContext.getApplicationContext();
new JpaTestRepositoryManagement(applicationContext.getBean(TenantAwareCacheManager.class),
applicationContext.getBean(SystemSecurityContext.class),
applicationContext.getBean(SystemManagement.class)).clearTestRepository();
}
}

View File

@@ -20,7 +20,7 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
public class JpaTestRepositoryManagement implements TestRepositoryManagement {
public class JpaTestRepositoryManagement {
private static final Logger LOGGER = LoggerFactory.getLogger(JpaTestRepositoryManagement.class);
private static final Pageable PAGE = new PageRequest(0, 400, new Sort(Direction.ASC, "id"));
@@ -48,7 +48,6 @@ public class JpaTestRepositoryManagement implements TestRepositoryManagement {
this.systemManagement = systemManagement;
}
@Override
public void clearTestRepository() {
deleteAllRepos();
cacheManager.getDirectCacheNames().forEach(name -> cacheManager.getDirectCache(name).clear());

View File

@@ -1,27 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.test.util;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
public class TestContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static ConfigurableApplicationContext getContext() {
return (ConfigurableApplicationContext) applicationContext;
}
@Override
public void setApplicationContext(final ApplicationContext context) {
applicationContext = context;
}
}

View File

@@ -1,22 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.test.util;
/**
* Repository support for tests.
*
*/
@FunctionalInterface
public interface TestRepositoryManagement {
/**
* Empty the test repository.
*/
void clearTestRepository();
}