DATACMNS-589 - Integrated RepositoryInvoker abstraction from Spring Data REST.
Replaced CrudInvoker with the more sophisticated and flexible RepositoryInvoker originating from Spring Data REST. Slightly refined the API and added a lot more unit tests. Refactored usage of CrudInvoker to use a DefaultRepositoryInvokerFactory and create RepositoryInvokers for the domain types.
This commit is contained in:
@@ -23,6 +23,8 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -46,8 +48,8 @@ public class RepositoryComponentProviderUnitTests {
|
||||
RepositoryComponentProvider provider = new RepositoryComponentProvider(Collections.<TypeFilter> emptyList());
|
||||
Set<BeanDefinition> components = provider.findCandidateComponents("org.springframework.data.repository.sample");
|
||||
|
||||
assertThat(components.size(), is(1));
|
||||
assertThat(components.iterator().next().getBeanClassName(), is(SampleAnnotatedRepository.class.getName()));
|
||||
assertThat(components.size(), is(3));
|
||||
assertThat(components, hasItem(BeanDefinitionOfTypeMatcher.beanDefinitionOfType(SampleAnnotatedRepository.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -59,7 +61,7 @@ public class RepositoryComponentProviderUnitTests {
|
||||
Set<BeanDefinition> components = provider.findCandidateComponents("org.springframework.data.repository");
|
||||
|
||||
assertThat(components.size(), is(1));
|
||||
assertThat(components.iterator().next().getBeanClassName(), is(MyOtherRepository.class.getName()));
|
||||
assertThat(components, hasItem(BeanDefinitionOfTypeMatcher.beanDefinitionOfType(MyOtherRepository.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,5 +81,40 @@ public class RepositoryComponentProviderUnitTests {
|
||||
Matchers.<BeanDefinition> hasItem(hasProperty("beanClassName", is(nestedRepositoryClassName))));
|
||||
}
|
||||
|
||||
static class BeanDefinitionOfTypeMatcher extends BaseMatcher<BeanDefinition> {
|
||||
|
||||
private final Class<?> expectedType;
|
||||
|
||||
private BeanDefinitionOfTypeMatcher(Class<?> expectedType) {
|
||||
this.expectedType = expectedType;
|
||||
}
|
||||
|
||||
public static BeanDefinitionOfTypeMatcher beanDefinitionOfType(Class<?> expectedType) {
|
||||
return new BeanDefinitionOfTypeMatcher(expectedType);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.hamcrest.Matcher#matches(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(Object item) {
|
||||
|
||||
if (!(item instanceof BeanDefinition)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BeanDefinition definition = (BeanDefinition) item;
|
||||
return definition.getBeanClassName().equals(expectedType.getName());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.hamcrest.SelfDescribing#describeTo(org.hamcrest.Description)
|
||||
*/
|
||||
@Override
|
||||
public void describeTo(Description description) {}
|
||||
}
|
||||
|
||||
public interface MyNestedRepository extends Repository<Person, Long> {}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
* Copyright 2012-2014 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.
|
||||
@@ -21,50 +21,62 @@ import static org.mockito.Mockito.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.repository.core.CrudInvoker;
|
||||
import org.springframework.data.repository.sample.Product;
|
||||
import org.springframework.data.repository.sample.ProductRepository;
|
||||
import org.springframework.data.repository.sample.SampleConfiguration;
|
||||
import org.springframework.data.repository.sample.User;
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link UnmarshallingRepositoryInitializer}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = SampleConfiguration.class)
|
||||
public class ResourceReaderRepositoryInitializerUnitTests {
|
||||
|
||||
@Mock ResourceReader reader;
|
||||
@Mock Repositories repositories;
|
||||
@Mock Resource resource;
|
||||
@Mock CrudInvoker<Object> invoker;
|
||||
@Autowired ProductRepository productRepository;
|
||||
@Autowired Repositories repositories;
|
||||
|
||||
@Mock ApplicationEventPublisher publisher;
|
||||
ApplicationEventPublisher publisher;
|
||||
ResourceReader reader;
|
||||
Resource resource;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
this.reader = mock(ResourceReader.class);
|
||||
this.publisher = mock(ApplicationEventPublisher.class);
|
||||
this.resource = mock(Resource.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void storesSingleObjectCorrectly() throws Exception {
|
||||
|
||||
Object reference = new Object();
|
||||
|
||||
Product reference = new Product();
|
||||
setUpReferenceAndInititalize(reference);
|
||||
|
||||
verify(invoker, times(1)).invokeSave(reference);
|
||||
verify(productRepository).save(reference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void storesCollectionOfObjectsCorrectly() throws Exception {
|
||||
|
||||
Object object = new Object();
|
||||
Collection<Object> reference = Collections.singletonList(object);
|
||||
Product product = new Product();
|
||||
Collection<Product> reference = Collections.singletonList(product);
|
||||
|
||||
setUpReferenceAndInititalize(reference);
|
||||
|
||||
verify(invoker, times(1)).invokeSave(object);
|
||||
verify(productRepository, times(1)).save(product);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,7 +85,7 @@ public class ResourceReaderRepositoryInitializerUnitTests {
|
||||
@Test
|
||||
public void emitsRepositoriesPopulatedEventIfPublisherConfigured() throws Exception {
|
||||
|
||||
RepositoryPopulator populator = setUpReferenceAndInititalize(new Object(), publisher);
|
||||
RepositoryPopulator populator = setUpReferenceAndInititalize(new User(), publisher);
|
||||
|
||||
ApplicationEvent event = new RepositoriesPopulatedEvent(populator, repositories);
|
||||
verify(publisher, times(1)).publishEvent(event);
|
||||
@@ -83,7 +95,6 @@ public class ResourceReaderRepositoryInitializerUnitTests {
|
||||
throws Exception {
|
||||
|
||||
when(reader.readFrom(any(Resource.class), any(ClassLoader.class))).thenReturn(reference);
|
||||
when(repositories.getCrudInvoker(Object.class)).thenReturn(invoker);
|
||||
|
||||
ResourceReaderRepositoryPopulator populator = new ResourceReaderRepositoryPopulator(reader);
|
||||
populator.setResources(resource);
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright 2014 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.repository.invoker;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.repository.invoker.RepositoryInvocationTestUtils.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.invoker.RepositoryInvocationTestUtils.VerifyingMethodInterceptor;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CrudRepositoryInvoker}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CrudRepositoryInvokerUnitTests {
|
||||
|
||||
@Mock PersonRepository personRepository;
|
||||
@Mock OrderRepository orderRepository;
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589, DATAREST-216
|
||||
*/
|
||||
@Test
|
||||
public void invokesRedeclaredSave() {
|
||||
getInvokerFor(orderRepository, expectInvocationOnType(OrderRepository.class)).invokeSave(new Order());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589, DATAREST-216
|
||||
*/
|
||||
@Test
|
||||
public void invokesRedeclaredFindOne() {
|
||||
getInvokerFor(orderRepository, expectInvocationOnType(OrderRepository.class)).invokeFindOne(1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesRedeclaredDelete() throws Exception {
|
||||
getInvokerFor(orderRepository, expectInvocationOnType(OrderRepository.class)).invokeDelete(1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesSaveOnCrudRepository() throws Exception {
|
||||
|
||||
Method method = CrudRepository.class.getMethod("save", Object.class);
|
||||
getInvokerFor(personRepository, expectInvocationOf(method)).invokeSave(new Person());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesFindOneOnCrudRepository() throws Exception {
|
||||
|
||||
Method method = CrudRepository.class.getMethod("findOne", Serializable.class);
|
||||
getInvokerFor(personRepository, expectInvocationOf(method)).invokeFindOne(1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589, DATAREST-216
|
||||
*/
|
||||
@Test
|
||||
public void invokesDeleteOnCrudRepository() throws Exception {
|
||||
|
||||
Method method = CrudRepository.class.getMethod("delete", Serializable.class);
|
||||
getInvokerFor(personRepository, expectInvocationOf(method)).invokeDelete(1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesFindAllOnCrudRepository() throws Exception {
|
||||
|
||||
Method method = CrudRepository.class.getMethod("findAll");
|
||||
|
||||
getInvokerFor(orderRepository, expectInvocationOf(method)).invokeFindAll((Pageable) null);
|
||||
getInvokerFor(orderRepository, expectInvocationOf(method)).invokeFindAll((Sort) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesCustomFindAllTakingASort() throws Exception {
|
||||
|
||||
CrudWithFindAllWithSort repository = mock(CrudWithFindAllWithSort.class);
|
||||
|
||||
Method findAllWithSort = CrudWithFindAllWithSort.class.getMethod("findAll", Sort.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(findAllWithSort)).invokeFindAll((Pageable) null);
|
||||
getInvokerFor(repository, expectInvocationOf(findAllWithSort)).invokeFindAll(new PageRequest(0, 10));
|
||||
getInvokerFor(repository, expectInvocationOf(findAllWithSort)).invokeFindAll((Sort) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesCustomFindAllTakingAPageable() throws Exception {
|
||||
|
||||
CrudWithFindAllWithPageable repository = mock(CrudWithFindAllWithPageable.class);
|
||||
|
||||
Method findAllWithPageable = CrudWithFindAllWithPageable.class.getMethod("findAll", Pageable.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(findAllWithPageable)).invokeFindAll((Pageable) null);
|
||||
getInvokerFor(repository, expectInvocationOf(findAllWithPageable)).invokeFindAll(new PageRequest(0, 10));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private static RepositoryInvoker getInvokerFor(Object repository, VerifyingMethodInterceptor interceptor) {
|
||||
|
||||
Object proxy = getVerifyingRepositoryProxy(repository, interceptor);
|
||||
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(repository.getClass().getInterfaces()[0]);
|
||||
GenericConversionService conversionService = new DefaultFormattingConversionService();
|
||||
|
||||
return new CrudRepositoryInvoker((CrudRepository) proxy, metadata, conversionService);
|
||||
}
|
||||
|
||||
static class Order {}
|
||||
|
||||
interface OrderRepository extends CrudRepository<Order, Long> {
|
||||
|
||||
@Override
|
||||
<S extends Order> S save(S entity);
|
||||
|
||||
@Override
|
||||
Order findOne(Long id);
|
||||
|
||||
@Override
|
||||
void delete(Long id);
|
||||
}
|
||||
|
||||
static class Person {}
|
||||
|
||||
interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
|
||||
|
||||
Page<Person> findByFirstName(@Param("firstName") String firstName, Pageable pageable);
|
||||
|
||||
Page<Person> findByCreatedUsingISO8601Date(@Param("date") @DateTimeFormat(iso = ISO.DATE_TIME) Date date,
|
||||
Pageable pageable);
|
||||
}
|
||||
|
||||
interface CrudWithFindAllWithSort extends CrudRepository<Order, Long> {
|
||||
|
||||
List<Order> findAll(Sort sort);
|
||||
}
|
||||
|
||||
interface CrudWithFindAllWithPageable extends CrudRepository<Order, Long> {
|
||||
|
||||
List<Order> findAll(Pageable sort);
|
||||
}
|
||||
|
||||
interface CrudWithRedeclaredDelete extends CrudRepository<Order, Long> {
|
||||
|
||||
void delete(Long id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2014 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.repository.invoker;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.repository.sample.Product;
|
||||
import org.springframework.data.repository.sample.ProductRepository;
|
||||
import org.springframework.data.repository.sample.SampleConfiguration;
|
||||
import org.springframework.data.repository.sample.User;
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link DefaultRepositoryInvokerFactory}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = SampleConfiguration.class)
|
||||
public class DefaultRepositoryInvokerFactoryIntegrationTests {
|
||||
|
||||
@Autowired ProductRepository productRepository;
|
||||
@Autowired Repositories repositories;
|
||||
|
||||
RepositoryInvokerFactory factory;
|
||||
|
||||
@Rule public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.factory = new DefaultRepositoryInvokerFactory(repositories);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-410, DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void findOneShouldDelegateToAppropriateRepository() {
|
||||
|
||||
Mockito.reset(productRepository);
|
||||
Product product = new Product();
|
||||
when(productRepository.findOne(4711L)).thenReturn(product);
|
||||
|
||||
assertThat(factory.getInvokerFor(Product.class).invokeFindOne(4711L), is((Object) product));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-374, DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void shouldThrowMeaningfulExceptionWhenTheRepositoryForAGivenDomainClassCannotBeFound() {
|
||||
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectMessage("No repository found for domain type: ");
|
||||
exception.expectMessage(Object.class.getName());
|
||||
|
||||
factory.getInvokerFor(Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void returnsSameInvokerInstanceForSubsequentCalls() {
|
||||
|
||||
RepositoryInvoker invoker = factory.getInvokerFor(Product.class);
|
||||
|
||||
assertThat(factory.getInvokerFor(Product.class), is(invoker));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void createsReflectionRepositoryInvokerForRepositoryNotExtendingADedicatedBaseRepository() {
|
||||
|
||||
RepositoryInvoker invoker = factory.getInvokerFor(Product.class);
|
||||
|
||||
assertThat(invoker, is(instanceOf(ReflectionRepositoryInvoker.class)));
|
||||
assertThat(invoker, is(not(instanceOf(CrudRepositoryInvoker.class))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void createsCrudRepositoryInvokerForRepositoryExtendingCrudRepository() {
|
||||
|
||||
RepositoryInvoker invoker = factory.getInvokerFor(User.class);
|
||||
|
||||
assertThat(invoker, is(instanceOf(CrudRepositoryInvoker.class)));
|
||||
assertThat(invoker, is(not(instanceOf(PagingAndSortingRepositoryInvoker.class))));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2014 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.repository.invoker;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.repository.invoker.RepositoryInvocationTestUtils.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.invoker.RepositoryInvocationTestUtils.VerifyingMethodInterceptor;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PagingAndSortingRepositoryInvoker}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class PaginginAndSortingRepositoryInvokerUnitTests {
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesFindAllWithPageableByDefault() throws Exception {
|
||||
|
||||
Repository repository = mock(Repository.class);
|
||||
Method method = PagingAndSortingRepository.class.getMethod("findAll", Pageable.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll(new PageRequest(0, 10));
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll((Pageable) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesFindAllWithSortByDefault() throws Exception {
|
||||
|
||||
Repository repository = mock(Repository.class);
|
||||
Method method = PagingAndSortingRepository.class.getMethod("findAll", Sort.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll(new Sort("foo"));
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll((Sort) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesRedeclaredFindAllWithPageable() throws Exception {
|
||||
|
||||
RepositoryWithRedeclaredFindAllWithPageable repository = mock(RepositoryWithRedeclaredFindAllWithPageable.class);
|
||||
Method method = RepositoryWithRedeclaredFindAllWithPageable.class.getMethod("findAll", Pageable.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll(new PageRequest(0, 10));
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll((Pageable) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesRedeclaredFindAllWithSort() throws Exception {
|
||||
|
||||
RepositoryWithRedeclaredFindAllWithSort repository = mock(RepositoryWithRedeclaredFindAllWithSort.class);
|
||||
Method method = RepositoryWithRedeclaredFindAllWithSort.class.getMethod("findAll", Sort.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll(new Sort("foo"));
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll((Sort) null);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private static RepositoryInvoker getInvokerFor(Object repository) {
|
||||
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(repository.getClass().getInterfaces()[0]);
|
||||
GenericConversionService conversionService = new DefaultFormattingConversionService();
|
||||
|
||||
return new PagingAndSortingRepositoryInvoker((PagingAndSortingRepository) repository, metadata, conversionService);
|
||||
}
|
||||
|
||||
private static RepositoryInvoker getInvokerFor(Object repository, VerifyingMethodInterceptor interceptor) {
|
||||
return getInvokerFor(getVerifyingRepositoryProxy(repository, interceptor));
|
||||
}
|
||||
|
||||
interface Repository extends PagingAndSortingRepository<Object, Long> {}
|
||||
|
||||
interface RepositoryWithRedeclaredFindAllWithPageable extends PagingAndSortingRepository<Object, Long> {
|
||||
|
||||
Page<Object> findAll(Pageable pageable);
|
||||
}
|
||||
|
||||
interface RepositoryWithRedeclaredFindAllWithSort extends PagingAndSortingRepository<Object, Long> {
|
||||
|
||||
Page<Object> findAll(Sort sort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright 2013 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.repository.invoker;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.repository.invoker.RepositoryInvocationTestUtils.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.invoker.CrudRepositoryInvokerUnitTests.Person;
|
||||
import org.springframework.data.repository.invoker.CrudRepositoryInvokerUnitTests.PersonRepository;
|
||||
import org.springframework.data.repository.invoker.RepositoryInvocationTestUtils.VerifyingMethodInterceptor;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ReflectionRepositoryInvoker}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ReflectionRepositoryInvokerUnitTests {
|
||||
|
||||
static final Page<Person> EMPTY_PAGE = new PageImpl<Person>(Collections.<Person> emptyList());
|
||||
|
||||
ConversionService conversionService;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.conversionService = new DefaultFormattingConversionService();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesSaveMethodCorrectly() throws Exception {
|
||||
|
||||
ManualCrudRepository repository = mock(ManualCrudRepository.class);
|
||||
Method method = ManualCrudRepository.class.getMethod("save", Domain.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeSave(new Domain());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesFindOneCorrectly() throws Exception {
|
||||
|
||||
ManualCrudRepository repository = mock(ManualCrudRepository.class);
|
||||
Method method = ManualCrudRepository.class.getMethod("findOne", Long.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindOne("1");
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindOne(1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesDeleteWithDomainCorrectly() throws Exception {
|
||||
|
||||
RepoWithDomainDeleteAndFindOne repository = mock(RepoWithDomainDeleteAndFindOne.class);
|
||||
when(repository.findOne(1L)).thenReturn(new Domain());
|
||||
|
||||
Method findOneMethod = RepoWithDomainDeleteAndFindOne.class.getMethod("findOne", Long.class);
|
||||
Method deleteMethod = RepoWithDomainDeleteAndFindOne.class.getMethod("delete", Domain.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(findOneMethod, deleteMethod)).invokeDelete(1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesFindAllWithoutParameterCorrectly() throws Exception {
|
||||
|
||||
Method method = ManualCrudRepository.class.getMethod("findAll");
|
||||
ManualCrudRepository repository = mock(ManualCrudRepository.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll((Pageable) null);
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll(new PageRequest(0, 10));
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll((Sort) null);
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll(new Sort("foo"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesFindAllWithSortCorrectly() throws Exception {
|
||||
|
||||
Method method = RepoWithFindAllWithSort.class.getMethod("findAll", Sort.class);
|
||||
RepoWithFindAllWithSort repository = mock(RepoWithFindAllWithSort.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll((Pageable) null);
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll(new PageRequest(0, 10));
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll((Sort) null);
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll(new Sort("foo"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesFindAllWithPageableCorrectly() throws Exception {
|
||||
|
||||
Method method = RepoWithFindAllWithPageable.class.getMethod("findAll", Pageable.class);
|
||||
RepoWithFindAllWithPageable repository = mock(RepoWithFindAllWithPageable.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll((Pageable) null);
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeFindAll(new PageRequest(0, 10));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesQueryMethod() throws Exception {
|
||||
|
||||
HashMap<String, String[]> parameters = new HashMap<String, String[]>();
|
||||
parameters.put("firstName", new String[] { "John" });
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByFirstName", String.class, Pageable.class);
|
||||
PersonRepository repository = mock(PersonRepository.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeQueryMethod(method, parameters, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void considersFormattingAnnotationsOnQueryMethodParameters() throws Exception {
|
||||
|
||||
HashMap<String, String[]> parameters = new HashMap<String, String[]>();
|
||||
parameters.put("date", new String[] { "2013-07-18T10:49:00.000+02:00" });
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByCreatedUsingISO8601Date", Date.class, Pageable.class);
|
||||
PersonRepository repository = mock(PersonRepository.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeQueryMethod(method, parameters, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-335, DATAREST-346, DATACMNS-589
|
||||
*/
|
||||
@Test
|
||||
public void invokesOverriddenDeleteMethodCorrectly() throws Exception {
|
||||
|
||||
MyRepo repository = mock(MyRepo.class);
|
||||
Method method = CustomRepo.class.getMethod("delete", Long.class);
|
||||
|
||||
getInvokerFor(repository, expectInvocationOf(method)).invokeDelete("1");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsInvocationOfMissingDeleteMethod() {
|
||||
|
||||
RepositoryInvoker invoker = getInvokerFor(mock(EmptyRepository.class));
|
||||
|
||||
assertThat(invoker.hasDeleteMethod(), is(false));
|
||||
invoker.invokeDelete(1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsInvocationOfMissingFindOneMethod() {
|
||||
|
||||
RepositoryInvoker invoker = getInvokerFor(mock(EmptyRepository.class));
|
||||
|
||||
assertThat(invoker.hasFindOneMethod(), is(false));
|
||||
invoker.invokeFindOne(1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsInvocationOfMissingFindAllMethod() {
|
||||
|
||||
RepositoryInvoker invoker = getInvokerFor(mock(EmptyRepository.class));
|
||||
|
||||
assertThat(invoker.hasFindAllMethod(), is(false));
|
||||
invoker.invokeFindAll((Pageable) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-589
|
||||
*/
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsInvocationOfMissingSaveMethod() {
|
||||
|
||||
RepositoryInvoker invoker = getInvokerFor(mock(EmptyRepository.class));
|
||||
|
||||
assertThat(invoker.hasSaveMethod(), is(false));
|
||||
invoker.invokeSave(new Object());
|
||||
}
|
||||
|
||||
private static RepositoryInvoker getInvokerFor(Object repository) {
|
||||
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(repository.getClass().getInterfaces()[0]);
|
||||
GenericConversionService conversionService = new DefaultFormattingConversionService();
|
||||
|
||||
return new ReflectionRepositoryInvoker(repository, metadata, conversionService);
|
||||
}
|
||||
|
||||
private static RepositoryInvoker getInvokerFor(Object repository, VerifyingMethodInterceptor interceptor) {
|
||||
return getInvokerFor(getVerifyingRepositoryProxy(repository, interceptor));
|
||||
}
|
||||
|
||||
interface MyRepo extends CustomRepo, CrudRepository<Domain, Long> {}
|
||||
|
||||
class Domain {}
|
||||
|
||||
interface CustomRepo {
|
||||
void delete(Long id);
|
||||
}
|
||||
|
||||
interface EmptyRepository extends Repository<Domain, Long> {}
|
||||
|
||||
interface ManualCrudRepository extends Repository<Domain, Long> {
|
||||
|
||||
Domain findOne(Long id);
|
||||
|
||||
Iterable<Domain> findAll();
|
||||
|
||||
<T extends Domain> T save(T entity);
|
||||
|
||||
void delete(Long id);
|
||||
}
|
||||
|
||||
interface RepoWithFindAllWithoutParameters extends Repository<Domain, Long> {
|
||||
|
||||
List<Domain> findAll();
|
||||
}
|
||||
|
||||
interface RepoWithFindAllWithPageable extends Repository<Domain, Long> {
|
||||
|
||||
Page<Domain> findAll(Pageable pageable);
|
||||
}
|
||||
|
||||
interface RepoWithFindAllWithSort extends Repository<Domain, Long> {
|
||||
|
||||
Page<Domain> findAll(Sort sort);
|
||||
}
|
||||
|
||||
interface RepoWithDomainDeleteAndFindOne extends Repository<Domain, Long> {
|
||||
|
||||
Domain findOne(Long id);
|
||||
|
||||
void delete(Domain entity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2014 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.repository.invoker;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
|
||||
/**
|
||||
* Utility methods to create {@link RepositoryInvoker} instances that get a verifying proxy attached so that the
|
||||
* invocation of a given target methods or type can be verified.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class RepositoryInvocationTestUtils {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getVerifyingRepositoryProxy(T target, VerifyingMethodInterceptor interceptor) {
|
||||
|
||||
ProxyFactory factory = new ProxyFactory();
|
||||
factory.setInterfaces(target.getClass().getInterfaces());
|
||||
factory.setTarget(target);
|
||||
factory.addAdvice(interceptor);
|
||||
|
||||
return (T) factory.getProxy();
|
||||
}
|
||||
|
||||
public static VerifyingMethodInterceptor expectInvocationOnType(Class<?> type) {
|
||||
return new VerifyingMethodInterceptor(type, new Method[0]);
|
||||
}
|
||||
|
||||
public static VerifyingMethodInterceptor expectInvocationOf(Method... methods) {
|
||||
return new VerifyingMethodInterceptor(null, methods);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MethodInterceptor} to verifiy the invocation was triggered on the given type.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static final class VerifyingMethodInterceptor implements MethodInterceptor {
|
||||
|
||||
private final Class expectedInvocationTarget;
|
||||
private final List<Method> methods;
|
||||
|
||||
private VerifyingMethodInterceptor(Class<?> expectedInvocationTarget, Method... methods) {
|
||||
this.expectedInvocationTarget = expectedInvocationTarget;
|
||||
this.methods = Arrays.asList(methods);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
|
||||
if (!methods.isEmpty()) {
|
||||
assertThat(methods, hasItem(invocation.getMethod()));
|
||||
} else {
|
||||
|
||||
Class<?> type = invocation.getMethod().getDeclaringClass();
|
||||
|
||||
assertThat("Expected methods invocation on " + expectedInvocationTarget + " but was invoked on " + type + "!",
|
||||
type, is(equalTo(expectedInvocationTarget)));
|
||||
}
|
||||
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package org.springframework.data.repository.sample;
|
||||
|
||||
public class Product {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.springframework.data.repository.sample;
|
||||
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
public interface ProductRepository extends Repository<Product, Long> {
|
||||
|
||||
Product findOne(Long id);
|
||||
|
||||
Product save(Product product);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.springframework.data.repository.sample;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.DummyRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
|
||||
@Configuration
|
||||
public class SampleConfiguration {
|
||||
|
||||
@Autowired ApplicationContext context;
|
||||
|
||||
@Bean
|
||||
public Repositories repositories() {
|
||||
return new Repositories(context);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RepositoryFactoryBeanSupport<Repository<User, Long>, User, Long> userRepositoryFactory() {
|
||||
|
||||
DummyRepositoryFactoryBean<Repository<User, Long>, User, Long> factory = new DummyRepositoryFactoryBean<Repository<User, Long>, User, Long>();
|
||||
factory.setRepositoryInterface(UserRepository.class);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RepositoryFactoryBeanSupport<Repository<Product, Long>, Product, Long> productRepositoryFactory(
|
||||
ProductRepository productRepository) {
|
||||
|
||||
DummyRepositoryFactoryBean<Repository<Product, Long>, Product, Long> factory = new DummyRepositoryFactoryBean<Repository<Product, Long>, Product, Long>();
|
||||
factory.setRepositoryInterface(ProductRepository.class);
|
||||
factory.setCustomImplementation(productRepository);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ProductRepository productRepository() {
|
||||
return mock(ProductRepository.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package org.springframework.data.repository.sample;
|
||||
|
||||
public class User {}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.springframework.data.repository.sample;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
public interface UserRepository extends CrudRepository<User, Long> {
|
||||
|
||||
}
|
||||
@@ -38,6 +38,7 @@ import org.springframework.data.repository.core.support.DummyRepositoryFactoryBe
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SuppressWarnings("deprecation")
|
||||
public class DomainClassPropertyEditorRegistrarUnitTests {
|
||||
|
||||
@Mock PropertyEditorRegistry registry;
|
||||
|
||||
@@ -28,8 +28,8 @@ import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.data.domain.Persistable;
|
||||
import org.springframework.data.repository.core.CrudInvoker;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.data.repository.invoker.RepositoryInvoker;
|
||||
|
||||
/**
|
||||
* Unit test for {@link DomainClassPropertyEditor}.
|
||||
@@ -42,14 +42,14 @@ public class DomainClassPropertyEditorUnitTests {
|
||||
DomainClassPropertyEditor<User, Integer> editor;
|
||||
|
||||
@Mock PropertyEditorRegistry registry;
|
||||
@Mock CrudInvoker<User> userRepository;
|
||||
@Mock RepositoryInvoker invoker;
|
||||
@Mock EntityInformation<User, Integer> information;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
when(information.getIdType()).thenReturn(Integer.class);
|
||||
editor = new DomainClassPropertyEditor<User, Integer>(userRepository, information, registry);
|
||||
editor = new DomainClassPropertyEditor<User, Integer>(invoker, information, registry);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -57,11 +57,11 @@ public class DomainClassPropertyEditorUnitTests {
|
||||
|
||||
User user = new User(1);
|
||||
when(information.getId(user)).thenReturn(user.getId());
|
||||
when(userRepository.invokeFindOne(1)).thenReturn(user);
|
||||
when(invoker.invokeFindOne(1)).thenReturn(user);
|
||||
|
||||
editor.setAsText("1");
|
||||
|
||||
verify(userRepository, times(1)).invokeFindOne(1);
|
||||
verify(invoker, times(1)).invokeFindOne(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 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.repository.support;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.core.CrudInvoker;
|
||||
import org.springframework.data.repository.core.CrudMethods;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ReflectionRepositoryInvoker}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ReflectionRepositoryInvokerUnitTests {
|
||||
|
||||
@Mock CrudRepository<Object, Serializable> repo;
|
||||
@Mock CrudMethods methods;
|
||||
|
||||
@Test
|
||||
public void createsInvokerForRepositoryExposingBothFindAllAndSaveMethod() {
|
||||
|
||||
when(methods.hasFindOneMethod()).thenReturn(true);
|
||||
when(methods.hasSaveMethod()).thenReturn(true);
|
||||
|
||||
new ReflectionRepositoryInvoker<Object>(repo, methods);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullRepository() {
|
||||
|
||||
when(methods.hasFindOneMethod()).thenReturn(true);
|
||||
when(methods.hasSaveMethod()).thenReturn(true);
|
||||
|
||||
new ReflectionRepositoryInvoker<Object>(null, methods);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsRepositoryIfItDoesntExposeAFindOneMethod() {
|
||||
|
||||
when(methods.hasFindOneMethod()).thenReturn(false);
|
||||
when(methods.hasSaveMethod()).thenReturn(true);
|
||||
|
||||
new ReflectionRepositoryInvoker<Object>(repo, methods);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsRepositoryIfItDoesntExposeASaveMethod() {
|
||||
|
||||
when(methods.hasFindOneMethod()).thenReturn(true);
|
||||
when(methods.hasSaveMethod()).thenReturn(false);
|
||||
|
||||
new ReflectionRepositoryInvoker<Object>(repo, methods);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-410
|
||||
*/
|
||||
@Test
|
||||
public void invokesFindOneCorrectly() throws Exception {
|
||||
|
||||
when(methods.hasFindOneMethod()).thenReturn(true);
|
||||
when(methods.hasSaveMethod()).thenReturn(true);
|
||||
when(methods.getFindOneMethod()).thenReturn(CrudRepository.class.getMethod("findOne", Serializable.class));
|
||||
|
||||
CrudInvoker<Object> invoker = new ReflectionRepositoryInvoker<Object>(repo, methods);
|
||||
invoker.invokeFindOne(1L);
|
||||
|
||||
verify(repo, times(1)).findOne(1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-410
|
||||
*/
|
||||
@Test
|
||||
public void invokesSaveCorrectly() throws Exception {
|
||||
|
||||
when(methods.hasFindOneMethod()).thenReturn(true);
|
||||
when(methods.hasSaveMethod()).thenReturn(true);
|
||||
when(methods.getSaveMethod()).thenReturn(CrudRepository.class.getMethod("save", Object.class));
|
||||
|
||||
CrudInvoker<Object> invoker = new ReflectionRepositoryInvoker<Object>(repo, methods);
|
||||
Object object = new Object();
|
||||
invoker.invokeSave(object);
|
||||
|
||||
verify(repo, times(1)).save(object);
|
||||
}
|
||||
}
|
||||
@@ -21,16 +21,11 @@ import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.CrudInvoker;
|
||||
import org.springframework.data.repository.core.support.DummyRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
|
||||
import org.springframework.data.repository.sample.Product;
|
||||
import org.springframework.data.repository.sample.ProductRepository;
|
||||
import org.springframework.data.repository.sample.SampleConfiguration;
|
||||
import org.springframework.data.repository.sample.User;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@@ -41,45 +36,9 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@ContextConfiguration(classes = SampleConfiguration.class)
|
||||
public class RepositoriesIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Autowired ApplicationContext context;
|
||||
|
||||
@Bean
|
||||
public Repositories repositories() {
|
||||
return new Repositories(context);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RepositoryFactoryBeanSupport<Repository<User, Long>, User, Long> userRepositoryFactory() {
|
||||
|
||||
DummyRepositoryFactoryBean<Repository<User, Long>, User, Long> factory = new DummyRepositoryFactoryBean<Repository<User, Long>, User, Long>();
|
||||
factory.setRepositoryInterface(UserRepository.class);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RepositoryFactoryBeanSupport<Repository<Product, Long>, Product, Long> productRepositoryFactory(
|
||||
ProductRepository productRepository) {
|
||||
|
||||
DummyRepositoryFactoryBean<Repository<Product, Long>, Product, Long> factory = new DummyRepositoryFactoryBean<Repository<Product, Long>, Product, Long>();
|
||||
factory.setRepositoryInterface(ProductRepository.class);
|
||||
factory.setCustomImplementation(productRepository);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ProductRepository productRepository() {
|
||||
return mock(ProductRepository.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired Repositories repositories;
|
||||
@Autowired ProductRepository productRepository;
|
||||
|
||||
@@ -91,14 +50,6 @@ public class RepositoriesIntegrationTests {
|
||||
assertThat(repositories.hasRepositoryFor(Product.class), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsCrudInvokersCorrectly() {
|
||||
|
||||
assertThat(repositories, is(notNullValue()));
|
||||
assertThat(repositories.getCrudInvoker(User.class), is(instanceOf(CrudRepositoryInvoker.class)));
|
||||
assertThat(repositories.getCrudInvoker(Product.class), is(instanceOf(ReflectionRepositoryInvoker.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-376
|
||||
*/
|
||||
@@ -108,36 +59,4 @@ public class RepositoriesIntegrationTests {
|
||||
User user = mock(User.class);
|
||||
assertThat(repositories.getPersistentEntity(user.getClass()), is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-410
|
||||
*/
|
||||
@Test
|
||||
public void findOneShouldDelegateToAppropriateRepository() {
|
||||
|
||||
Mockito.reset(productRepository);
|
||||
Product product = new Product();
|
||||
when(productRepository.findOne(4711L)).thenReturn(product);
|
||||
|
||||
CrudInvoker<Product> crudInvoker = repositories.getCrudInvoker(Product.class);
|
||||
|
||||
assertThat(crudInvoker.invokeFindOne(4711L), is(product));
|
||||
}
|
||||
|
||||
static class User {
|
||||
|
||||
}
|
||||
|
||||
interface UserRepository extends CrudRepository<User, Long> {
|
||||
|
||||
}
|
||||
|
||||
public static class Product {}
|
||||
|
||||
public static interface ProductRepository extends Repository<Product, Long> {
|
||||
|
||||
Product findOne(Long id);
|
||||
|
||||
Product save(Product product);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,9 +25,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
@@ -59,8 +57,6 @@ public class RepositoriesUnitTests {
|
||||
|
||||
GenericApplicationContext context;
|
||||
|
||||
@Rule public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@@ -112,38 +108,13 @@ public class RepositoriesUnitTests {
|
||||
assertThat(repositories.getPersistentEntity(Address.class), is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-374
|
||||
*/
|
||||
@Test
|
||||
public void shouldThrowMeaningfulExceptionWhenTheRepositoryForAGivenDomainClassCannotBeFound() {
|
||||
class Person {}
|
||||
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectMessage(containsString("No repository found for domain class: "));
|
||||
class Address {}
|
||||
|
||||
Repositories repositories = new Repositories(context);
|
||||
repositories.getCrudInvoker(EntityWithoutRepository.class);
|
||||
}
|
||||
interface PersonRepository extends CrudRepository<Person, Long> {}
|
||||
|
||||
class Person {
|
||||
|
||||
}
|
||||
|
||||
class Address {
|
||||
|
||||
}
|
||||
|
||||
class EntityWithoutRepository {
|
||||
|
||||
}
|
||||
|
||||
interface PersonRepository extends CrudRepository<Person, Long> {
|
||||
|
||||
}
|
||||
|
||||
interface AddressRepository extends Repository<Address, Long> {
|
||||
|
||||
}
|
||||
interface AddressRepository extends Repository<Address, Long> {}
|
||||
|
||||
static class SampleRepoFactoryInformation<T, S extends Serializable> implements RepositoryFactoryInformation<T, S> {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user