/*
* Copyright 2012 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
*
* 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 org.springframework.data.gemfire.repository.cdi;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.ProcessBean;
import javax.inject.Qualifier;
import org.apache.geode.cache.Region;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
import org.springframework.data.gemfire.repository.GemfireRepository;
/**
* The GemfireRepositoryExtensionTest class is a test suite of unit tests testing the contract and proper functionality
* of the {@link GemfireRepositoryExtension} class in a Java EE CDI context.
*
* @author John Blum
* @see javax.enterprise.inject.spi.Bean
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.springframework.data.gemfire.mapping.GemfireMappingContext
* @see org.springframework.data.gemfire.repository.GemfireRepository
* @see org.springframework.data.gemfire.repository.cdi.GemfireRepositoryExtension
* @since 1.0.0
*/
@SuppressWarnings("unchecked")
public class GemfireRepositoryExtensionTest {
private GemfireRepositoryExtension repositoryExtension;
@Before
public void setup() {
repositoryExtension = new GemfireRepositoryExtension();
}
protected <T> Set<T> asSet(T... array) {
return new HashSet<T>(Arrays.asList(array));
}
protected Annotation mockAnnotation(Class annotationType) {
Annotation mockAnnotation = mock(Annotation.class);
when(mockAnnotation.annotationType()).thenReturn(annotationType);
return mockAnnotation;
}
@Test
public void processBeanIdentifiesAndProcessesRegionBeanCorrectly() {
ProcessBean<Region> mockProcessBean = mock(ProcessBean.class);
Bean<Region> mockBean = mock(Bean.class);
when(mockProcessBean.getBean()).thenReturn(mockBean);
when(mockBean.getTypes()).thenReturn(Collections.singleton((Type) Region.class));
assertThat(repositoryExtension.regionBeans.isEmpty(), is(true));
repositoryExtension.processBean(mockProcessBean);
assertThat(repositoryExtension.regionBeans.contains(mockBean), is(true));
verify(mockProcessBean, times(1)).getBean();
verify(mockBean, times(1)).getTypes();
}
@Test
public void processBeanIdentifiesAndProcessesGemfireMappingContextBeanCorrectly() {
ProcessBean<GemfireMappingContext> mockProcessBean = mock(ProcessBean.class);
Bean<GemfireMappingContext> mockBean = mock(Bean.class);
Set<Annotation> expectedQualifiers = asSet(mockAnnotation(SpringDataRepo.class),
mockAnnotation(GemfireRepo.class));
when(mockProcessBean.getBean()).thenReturn(mockBean);
when(mockBean.getTypes()).thenReturn(Collections.singleton((Type) GemfireMappingContext.class));
when(mockBean.getQualifiers()).thenReturn(expectedQualifiers);
assertThat(repositoryExtension.mappingContexts.isEmpty(), is(true));
repositoryExtension.processBean(mockProcessBean);
assertThat(repositoryExtension.mappingContexts.containsKey(expectedQualifiers), is(true));
assertThat(repositoryExtension.mappingContexts.get(expectedQualifiers), is(equalTo(mockBean)));
verify(mockProcessBean, times(1)).getBean();
verify(mockBean, times(2)).getTypes();
verify(mockBean, times(2)).getQualifiers();
}
@Test
public void processBeanIgnoresNonRegionNonGemfireMappingContextBeansProperly() {
ProcessBean<Object> mockProcessBean = mock(ProcessBean.class);
Bean<Object> mockBean = mock(Bean.class);
when(mockProcessBean.getBean()).thenReturn(mockBean);
when(mockBean.getTypes()).thenReturn(Collections.singleton((Type) Object.class));
assertThat(repositoryExtension.mappingContexts.isEmpty(), is(true));
assertThat(repositoryExtension.regionBeans.isEmpty(), is(true));
repositoryExtension.processBean(mockProcessBean);
assertThat(repositoryExtension.mappingContexts.isEmpty(), is(true));
assertThat(repositoryExtension.regionBeans.isEmpty(), is(true));
verify(mockProcessBean, times(1)).getBean();
verify(mockBean, times(1)).getTypes();
}
@Test
public void afterBeanDiscoveryRegistersRepositoryBean() {
AfterBeanDiscovery mockAfterBeanDiscovery = mock(AfterBeanDiscovery.class);
final Set<Annotation> expectedQualifiers = asSet(mockAnnotation(SpringDataRepo.class),
mockAnnotation(GemfireRepo.class));
doAnswer(new Answer<Void>() {
public Void answer(final InvocationOnMock invocation) throws Throwable {
GemfireRepositoryBean<?> repositoryBean = invocation.getArgument(0);
assertThat(repositoryBean, is(notNullValue()));
assertThat((Class<TestRepository>) repositoryBean.getBeanClass(), is(equalTo(TestRepository.class)));
assertThat(repositoryBean.getQualifiers(), is(equalTo(expectedQualifiers)));
return null;
}
}).when(mockAfterBeanDiscovery).addBean(isA(GemfireRepositoryBean.class));
GemfireRepositoryExtension repositoryExtension = new GemfireRepositoryExtension() {
@Override protected Iterable<Map.Entry<Class<?>, Set<Annotation>>> getRepositoryTypes() {
return Collections.<Class<?>, Set<Annotation>>singletonMap(TestRepository.class, expectedQualifiers).entrySet();
}
};
repositoryExtension.afterBeanDiscovery(mockAfterBeanDiscovery, mock(BeanManager.class));
verify(mockAfterBeanDiscovery, times(1)).addBean(isA(GemfireRepositoryBean.class));
}
@Qualifier
@interface GemfireRepo {
}
@Qualifier
@interface SpringDataRepo {
}
@GemfireRepo
@SpringDataRepo
interface TestRepository extends GemfireRepository<Object, Long> {
}
}