SGF-872 - Invoke SmartLifecycle callbacks when defining Regions based on Caching annotations.
This commit is contained in:
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newRuntimeException;
|
||||
@@ -23,6 +22,7 @@ import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
@@ -54,6 +54,7 @@ import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
@@ -62,6 +63,7 @@ import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport;
|
||||
import org.springframework.data.gemfire.config.annotation.support.CacheTypeAwareRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.support.CompositeLifecycle;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -114,6 +116,8 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
|
||||
|
||||
private ClientRegionShortcut clientRegionShortcut = ClientRegionShortcut.PROXY;
|
||||
|
||||
private CompositeLifecycle compositeLifecycle = new CompositeLifecycle();
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<RegionConfigurer> regionConfigurers = Collections.emptyList();
|
||||
|
||||
@@ -277,7 +281,6 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
|
||||
}
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("all")
|
||||
public BeanPostProcessor cachingAnnotationsRegionBeanRegistrar(ConfigurableBeanFactory beanFactory) {
|
||||
|
||||
return new BeanPostProcessor() {
|
||||
@@ -319,6 +322,8 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
|
||||
|
||||
regionFactoryBean.afterPropertiesSet();
|
||||
|
||||
this.compositeLifecycle.add(regionFactoryBean);
|
||||
|
||||
Optional.ofNullable(regionFactoryBean.getObject())
|
||||
.ifPresent(region -> beanFactory.registerSingleton(cacheName, region));
|
||||
}
|
||||
@@ -332,7 +337,7 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
protected List<RegionConfigurer> resolveRegionConfigurers() {
|
||||
private List<RegionConfigurer> resolveRegionConfigurers() {
|
||||
|
||||
return Optional.ofNullable(this.regionConfigurers)
|
||||
.filter(regionConfigurers -> !regionConfigurers.isEmpty())
|
||||
@@ -340,6 +345,11 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
|
||||
Collections.singletonList(LazyResolvingComposableRegionConfigurer.create(getBeanFactory())));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Lifecycle cachingDefinedRegionsCompositeLifecycleBean() {
|
||||
return this.compositeLifecycle;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link CacheNameResolver} is a {@link FunctionalInterface} declaring a contract for all implementations
|
||||
* used to resolve all cache names declared and used by a Spring application. A resolver typically inspects
|
||||
@@ -373,14 +383,13 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
|
||||
|
||||
protected abstract Class<? extends Annotation>[] getMethodCacheAnnotationTypes();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Class[] append(Class[] annotationTypes, Class... additionalAnnotationTypes) {
|
||||
|
||||
List<Class> annotationTypeList = new ArrayList<>(Arrays.asList(annotationTypes));
|
||||
|
||||
Collections.addAll(annotationTypeList, additionalAnnotationTypes);
|
||||
|
||||
return annotationTypeList.toArray(new Class[annotationTypeList.size()]);
|
||||
return annotationTypeList.toArray(new Class[0]);
|
||||
}
|
||||
|
||||
protected Set<String> resolveCacheNames(Annotation annotation) {
|
||||
@@ -402,12 +411,9 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<String> resolveCacheNames(Class<?> type) {
|
||||
|
||||
Set<String> cacheNames = new HashSet<>();
|
||||
|
||||
cacheNames.addAll(resolveCacheNames(type, getClassCacheAnnotationTypes()));
|
||||
Set<String> cacheNames = new HashSet<>(resolveCacheNames(type, getClassCacheAnnotationTypes()));
|
||||
|
||||
stream(type.getMethods())
|
||||
.filter(method -> isUserLevelMethod(method))
|
||||
@@ -457,7 +463,6 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<String> resolveCacheNames(Class<?> type) {
|
||||
|
||||
Set<String> cacheNames = super.resolveCacheNames(type);
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.data.gemfire.support;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* A Spring {@link Lifecycle} that implements the {@literal Composite software design pattern} composing 1 or more
|
||||
* {@link Lifecycle} components as a single, logical, composite {@link Lifecycle} object.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.Iterable
|
||||
* @see org.springframework.context.Lifecycle
|
||||
* @see org.springframework.context.SmartLifecycle
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public final class CompositeLifecycle implements Iterable<Lifecycle>, SmartLifecycle {
|
||||
|
||||
private final List<Lifecycle> lifecycleComponents = new CopyOnWriteArrayList<>();
|
||||
|
||||
/**
|
||||
* Adds a {@link Lifecycle} object to this composite.
|
||||
*
|
||||
* @param lifecycleComponent {@link Lifecycle} object to add to this composite.
|
||||
* @return a boolean value if the {@link Lifecycle} object is not {@literal null}
|
||||
* and was successfully added to this composite.
|
||||
* @see #remove(Lifecycle)
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public boolean add(@NonNull Lifecycle lifecycleComponent) {
|
||||
return lifecycleComponent != null && this.lifecycleComponents.add(lifecycleComponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean value indicating whether this composite contains any {@link Lifecycle} objects.
|
||||
*
|
||||
* @return a boolean value indicating whether this composite contains any {@link Lifecycle} objects.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return this.lifecycleComponents.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Iterator} over the {@link Lifecycle} objects contained by this composite.
|
||||
*
|
||||
* @return an {@link Iterator} over the {@link Lifecycle} objects contained by this composite.
|
||||
* @see java.util.Iterator
|
||||
*/
|
||||
@Override
|
||||
public Iterator<Lifecycle> iterator() {
|
||||
return Collections.unmodifiableList(this.lifecycleComponents).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given {@link Lifecycle} object from this composite.
|
||||
*
|
||||
* @param lifecycleComponent {@link Lifecycle} object to remove.
|
||||
* @return a boolean if the {@link Lifecycle} object was part of this composite
|
||||
* and was able to be removed successfully.
|
||||
* @see #add(Lifecycle)
|
||||
*/
|
||||
public boolean remove(@Nullable Lifecycle lifecycleComponent) {
|
||||
return this.lifecycleComponents.remove(lifecycleComponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of {@link Lifecycle} objects contained by this composite.
|
||||
*
|
||||
* @return an integer value specifying the number of {@link Lifecycle} objects contained by this composite.
|
||||
*/
|
||||
public int size() {
|
||||
return this.lifecycleComponents.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether any {@link Lifecycle} object contained by this composite is running.
|
||||
*
|
||||
* @return a boolean value indicating whether any {@link Lifecycle} object
|
||||
* contained by this composite is running.
|
||||
* @see org.springframework.context.Lifecycle#isRunning()
|
||||
*/
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
|
||||
for (Lifecycle lifecycleComponent : this) {
|
||||
if (lifecycleComponent.isRunning()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts all {@link Lifecycle} objects contained by this composite.
|
||||
*
|
||||
* @see #stop()
|
||||
*/
|
||||
@Override
|
||||
public void start() {
|
||||
this.lifecycleComponents.forEach(Lifecycle::start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops all {@link Lifecycle} objects contained by this composite.
|
||||
*
|
||||
* @see #start()
|
||||
*/
|
||||
@Override
|
||||
public void stop() {
|
||||
this.lifecycleComponents.forEach(Lifecycle::stop);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.support;
|
||||
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.apache.geode.cache.InterestResultPolicy;
|
||||
import org.apache.geode.cache.Region;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.client.Interest;
|
||||
import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects;
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration Tests asserting that caching-defined {@link Region Regions} receive a {@link Lifecycle#start()} callback
|
||||
* to register interests.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.cache.annotation.Cacheable
|
||||
* @see org.springframework.context.Lifecycle
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.Interest
|
||||
* @see org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects
|
||||
* @see org.springframework.test.context.ContextConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @see <a href="https://jira.spring.io/browse/DATAGEODE-219">DATAGEODE-219</a>
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
@SuppressWarnings({ "unchecked", "unused" })
|
||||
public class CachingDefinedRegionsRegistersInterestsIntegrationTests {
|
||||
|
||||
private static final Interest testInterest =
|
||||
new Interest<>("TestKey", InterestResultPolicy.KEYS_VALUES, false, true);
|
||||
|
||||
@Resource(name = "CacheOne")
|
||||
private Region cacheOne;
|
||||
|
||||
@Resource(name = "CacheTwo")
|
||||
private Region cacheTwo;
|
||||
|
||||
@Test
|
||||
public void cachesRegisterInterestInTestKey() {
|
||||
|
||||
assertThat(this.cacheOne).isNotNull();
|
||||
assertThat(this.cacheOne.getName()).isEqualTo("CacheOne");
|
||||
assertThat(this.cacheTwo).isNotNull();
|
||||
assertThat(this.cacheTwo.getName()).isEqualTo("CacheTwo");
|
||||
|
||||
Arrays.asList(this.cacheOne, this.cacheTwo).forEach(cache -> {
|
||||
verify(cache, times(1))
|
||||
.registerInterest(eq(testInterest.getKey()), eq(testInterest.getPolicy()), eq(testInterest.isDurable()),
|
||||
eq(testInterest.isReceiveValues()));
|
||||
});
|
||||
}
|
||||
|
||||
@ClientCacheApplication
|
||||
@EnableCachingDefinedRegions
|
||||
@EnableGemFireMockObjects
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
RegionConfigurer interestsRegisteringRegionConfigurer() {
|
||||
|
||||
return new RegionConfigurer() {
|
||||
|
||||
@Override
|
||||
public void configure(String beanName, ClientRegionFactoryBean<?, ?> bean) {
|
||||
bean.setInterests(ArrayUtils.asArray(testInterest));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
CacheableServiceObject cacheableServiceObject() {
|
||||
return new CacheableServiceObject();
|
||||
}
|
||||
}
|
||||
|
||||
@Service
|
||||
static class CacheableServiceObject {
|
||||
|
||||
@Cacheable("CacheOne")
|
||||
public Object cacheableOperationOne(String input) {
|
||||
return "FROM-CACHE-ONE";
|
||||
}
|
||||
|
||||
@Cacheable("CacheTwo")
|
||||
public Object cacheableOperationTwo(String input) {
|
||||
return "FROM-CACHE-TWO";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.data.gemfire.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.Lifecycle;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link CompositeLifecycle}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.context.Lifecycle
|
||||
* @see org.springframework.data.gemfire.support.CompositeLifecycle
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public class CompositeLifecycleUnitTests {
|
||||
|
||||
private CompositeLifecycle compositeLifecycle;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.compositeLifecycle = new CompositeLifecycle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addLifecycleObjectToCompositeReturnsTrue() {
|
||||
|
||||
Lifecycle mockLifecycle = mock(Lifecycle.class);
|
||||
|
||||
assertThat(this.compositeLifecycle.add(mockLifecycle)).isTrue();
|
||||
assertThat(this.compositeLifecycle).isNotEmpty();
|
||||
assertThat(this.compositeLifecycle).hasSize(1);
|
||||
assertThat(this.compositeLifecycle).containsExactly(mockLifecycle);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addNullReturnsFalse() {
|
||||
|
||||
assertThat(this.compositeLifecycle.add(null)).isFalse();
|
||||
assertThat(this.compositeLifecycle).isEmpty();
|
||||
assertThat(this.compositeLifecycle).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeLifecycleObjectReturnsTrue() {
|
||||
|
||||
Lifecycle mockLifecycle = mock(Lifecycle.class);
|
||||
|
||||
assertThat(this.compositeLifecycle.add(mockLifecycle)).isTrue();
|
||||
assertThat(this.compositeLifecycle).isNotEmpty();
|
||||
assertThat(this.compositeLifecycle).hasSize(1);
|
||||
assertThat(this.compositeLifecycle.remove(mockLifecycle)).isTrue();
|
||||
assertThat(this.compositeLifecycle).isEmpty();
|
||||
assertThat(this.compositeLifecycle).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeNullReturnsFalse() {
|
||||
|
||||
assertThat(this.compositeLifecycle).isEmpty();
|
||||
assertThat(this.compositeLifecycle).hasSize(0);
|
||||
assertThat(this.compositeLifecycle.remove(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAutoStartupReturnsTrue() {
|
||||
assertThat(this.compositeLifecycle.isAutoStartup()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRunningWithAllRunningLifecycleObjectsReturnsTrue() {
|
||||
|
||||
Lifecycle mockLifecycleOne = mock(Lifecycle.class);
|
||||
Lifecycle mockLifecycleTwo = mock(Lifecycle.class);
|
||||
|
||||
when(mockLifecycleOne.isRunning()).thenReturn(true);
|
||||
|
||||
assertThat(this.compositeLifecycle.add(mockLifecycleOne)).isTrue();
|
||||
assertThat(this.compositeLifecycle.add(mockLifecycleTwo)).isTrue();
|
||||
assertThat(this.compositeLifecycle.isRunning()).isTrue();
|
||||
|
||||
verify(mockLifecycleOne, times(1)).isRunning();
|
||||
verify(mockLifecycleTwo, never()).isRunning();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRunningWithNoLifecycleObjectReturnsFalse() {
|
||||
assertThat(this.compositeLifecycle.isRunning()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRunningWithNoRunningLifecycleObjectsReturnsFalse() {
|
||||
|
||||
Lifecycle mockLifecycleOne = mock(Lifecycle.class);
|
||||
Lifecycle mockLifecycleTwo = mock(Lifecycle.class);
|
||||
|
||||
when(mockLifecycleOne.isRunning()).thenReturn(false);
|
||||
when(mockLifecycleTwo.isRunning()).thenReturn(false);
|
||||
|
||||
assertThat(this.compositeLifecycle.add(mockLifecycleOne)).isTrue();
|
||||
assertThat(this.compositeLifecycle.add(mockLifecycleTwo)).isTrue();
|
||||
assertThat(this.compositeLifecycle.isRunning()).isFalse();
|
||||
|
||||
verify(mockLifecycleOne, times(1)).isRunning();
|
||||
verify(mockLifecycleTwo, times(1)).isRunning();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRunningWithOneRunningLifecycleObjectsReturnsTrue() {
|
||||
|
||||
Lifecycle mockLifecycleOne = mock(Lifecycle.class);
|
||||
Lifecycle mockLifecycleTwo = mock(Lifecycle.class);
|
||||
|
||||
when(mockLifecycleOne.isRunning()).thenReturn(false);
|
||||
when(mockLifecycleTwo.isRunning()).thenReturn(true);
|
||||
|
||||
assertThat(this.compositeLifecycle.add(mockLifecycleOne)).isTrue();
|
||||
assertThat(this.compositeLifecycle.add(mockLifecycleTwo)).isTrue();
|
||||
assertThat(this.compositeLifecycle.isRunning()).isTrue();
|
||||
|
||||
verify(mockLifecycleOne, times(1)).isRunning();
|
||||
verify(mockLifecycleTwo, times(1)).isRunning();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startStartsAllLifecycleObjects() {
|
||||
|
||||
Lifecycle mockLifecycleOne = mock(Lifecycle.class);
|
||||
Lifecycle mockLifecycleTwo = mock(Lifecycle.class);
|
||||
|
||||
assertThat(this.compositeLifecycle.add(mockLifecycleOne)).isTrue();
|
||||
assertThat(this.compositeLifecycle.add(mockLifecycleTwo)).isTrue();
|
||||
|
||||
this.compositeLifecycle.start();
|
||||
|
||||
verify(mockLifecycleOne, times(1)).start();
|
||||
verify(mockLifecycleTwo, times(1)).start();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stopStopsAllLifecycleObjects() {
|
||||
|
||||
Lifecycle mockLifecycleOne = mock(Lifecycle.class);
|
||||
Lifecycle mockLifecycleTwo = mock(Lifecycle.class);
|
||||
|
||||
assertThat(this.compositeLifecycle.add(mockLifecycleOne)).isTrue();
|
||||
assertThat(this.compositeLifecycle.add(mockLifecycleTwo)).isTrue();
|
||||
|
||||
this.compositeLifecycle.stop();
|
||||
|
||||
verify(mockLifecycleOne, times(1)).stop();
|
||||
verify(mockLifecycleTwo, times(1)).stop();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user