/* * Copyright 2016-2017 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.core.support; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import io.reactivex.Flowable; import reactor.core.publisher.Flux; import rx.Observable; import java.lang.reflect.Method; import java.util.Optional; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; import org.reactivestreams.Publisher; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.reactive.ReactiveCrudRepository; import org.springframework.data.repository.reactive.ReactiveSortingRepository; import org.springframework.data.repository.reactive.RxJava1CrudRepository; import org.springframework.data.repository.reactive.RxJava2CrudRepository; /** * Unit tests for {@link ReactiveRepositoryInformation}. * * @author Mark Paluch * @author Oliver Gierke * @author Christoph Strobl */ @RunWith(MockitoJUnitRunner.class) public class ReactiveRepositoryInformationUnitTests { static final Class<ReactiveJavaInterfaceWithGenerics> REPOSITORY = ReactiveJavaInterfaceWithGenerics.class; @Test // DATACMNS-836 public void discoversRxJava1MethodWithoutComparingReturnType() throws Exception { Method reference = extractTargetMethodFromRepository(RxJava1InterfaceWithGenerics.class, "deleteAll"); assertEquals(ReactiveCrudRepository.class, reference.getDeclaringClass()); assertThat(reference.getName(), is("deleteAll")); } @Test // DATACMNS-836 public void discoversRxJava1MethodWithConvertibleArguments() throws Exception { Method reference = extractTargetMethodFromRepository(RxJava1InterfaceWithGenerics.class, "saveAll", Observable.class); assertEquals(ReactiveCrudRepository.class, reference.getDeclaringClass()); assertThat(reference.getName(), is("saveAll")); assertThat(reference.getParameterTypes()[0], is(equalTo(Publisher.class))); } @Test // DATACMNS-988 public void discoversRxJava2MethodWithoutComparingReturnType() throws Exception { Method reference = extractTargetMethodFromRepository(RxJava2InterfaceWithGenerics.class, "deleteAll"); assertEquals(ReactiveCrudRepository.class, reference.getDeclaringClass()); assertThat(reference.getName(), is("deleteAll")); } @Test // DATACMNS-988 public void discoversRxJava2MethodWithConvertibleArguments() throws Exception { Method reference = extractTargetMethodFromRepository(RxJava2InterfaceWithGenerics.class, "saveAll", Flowable.class); assertEquals(ReactiveCrudRepository.class, reference.getDeclaringClass()); assertThat(reference.getName(), is("saveAll")); assertThat(reference.getParameterTypes()[0], is(equalTo(Publisher.class))); } @Test // DATACMNS-836 public void discoversMethodAssignableArguments() throws Exception { Method reference = extractTargetMethodFromRepository(ReactiveSortingRepository.class, "saveAll", Publisher.class); assertEquals(ReactiveCrudRepository.class, reference.getDeclaringClass()); assertThat(reference.getName(), is("saveAll")); assertThat(reference.getParameterTypes()[0], is(equalTo(Publisher.class))); } @Test // DATACMNS-836 public void discoversMethodExactIterableArguments() throws Exception { Method reference = extractTargetMethodFromRepository(ReactiveJavaInterfaceWithGenerics.class, "saveAll", Iterable.class); assertEquals(ReactiveCrudRepository.class, reference.getDeclaringClass()); assertThat(reference.getName(), is("saveAll")); assertThat(reference.getParameterTypes()[0], is(equalTo(Iterable.class))); } @Test // DATACMNS-836 public void discoversMethodExactObjectArguments() throws Exception { Method reference = extractTargetMethodFromRepository(ReactiveJavaInterfaceWithGenerics.class, "save", Object.class); assertEquals(ReactiveCrudRepository.class, reference.getDeclaringClass()); assertThat(reference.getName(), is("save")); assertThat(reference.getParameterTypes()[0], is(equalTo(Object.class))); } @Test // DATACMNS-1023 public void usesCorrectSaveOverload() throws Exception { Method reference = extractTargetMethodFromRepository(DummyRepository.class, "saveAll", Iterable.class); assertThat(reference, is(ReactiveCrudRepository.class.getMethod("saveAll", Iterable.class))); } private Method extractTargetMethodFromRepository(Class<?> repositoryType, String methodName, Class<?>... args) throws NoSuchMethodException { RepositoryInformation information = new ReactiveRepositoryInformation(new DefaultRepositoryMetadata(repositoryType), REPOSITORY, Optional.empty()); return information.getTargetClassMethod(repositoryType.getMethod(methodName, args)); } interface RxJava1InterfaceWithGenerics extends RxJava1CrudRepository<User, String> {} interface RxJava2InterfaceWithGenerics extends RxJava2CrudRepository<User, String> {} interface ReactiveJavaInterfaceWithGenerics extends ReactiveCrudRepository<User, String> {} static abstract class DummyGenericReactiveRepositorySupport<T, ID> implements ReactiveCrudRepository<T, ID> { } interface DummyRepository extends ReactiveCrudRepository<User, Integer> { @Override <S extends User> Flux<S> saveAll(Iterable<S> entities); } static class User { String id; public String getId() { return id; } public void setId(String id) { this.id = id; } } }