diff --git a/spring-data-mock-sample-jpa/pom.xml b/spring-data-mock-sample-jpa/pom.xml
index 13814e9e..76887729 100644
--- a/spring-data-mock-sample-jpa/pom.xml
+++ b/spring-data-mock-sample-jpa/pom.xml
@@ -35,7 +35,7 @@
1.12.1.RELEASE
1.10.1.RELEASE
1.0.2
- 1.1.4
+ 1.1.5
6.9.6
1.3
UTF-8
diff --git a/spring-data-mock/pom.xml b/spring-data-mock/pom.xml
index b34c88eb..8461fba2 100644
--- a/spring-data-mock/pom.xml
+++ b/spring-data-mock/pom.xml
@@ -27,7 +27,7 @@
com.mmnaseri.utils
spring-data-mock
- 1.1.4
+ 1.1.5
Spring Data Mock
A framework for mocking Spring Data repositories
diff --git a/spring-data-mock/src/main/java/com/mmnaseri/utils/spring/data/proxy/impl/resolvers/SignatureDataOperationResolver.java b/spring-data-mock/src/main/java/com/mmnaseri/utils/spring/data/proxy/impl/resolvers/SignatureDataOperationResolver.java
index ee6047a3..52bc8e70 100644
--- a/spring-data-mock/src/main/java/com/mmnaseri/utils/spring/data/proxy/impl/resolvers/SignatureDataOperationResolver.java
+++ b/spring-data-mock/src/main/java/com/mmnaseri/utils/spring/data/proxy/impl/resolvers/SignatureDataOperationResolver.java
@@ -11,6 +11,7 @@
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Arrays;
+import java.util.LinkedList;
import java.util.List;
/**
@@ -50,9 +51,12 @@ public SignatureDataOperationResolver(List> mappings) {
return null;
}
- private static Method findMethod(Class> type, String name, Class>... parameterTypes) {
+ private Method findMethod(Class> type, String name, Class>... parameterTypes) {
log.debug("Attempting to look for the actual declaration of the method named '" + name + "' with parameter types " + Arrays.toString(parameterTypes) + " on the child type " + type);
Class> searchType = type;
+
+ List matchingMethods = new LinkedList<>();
+
while (searchType != null) {
log.trace("Looking at type " + type + " for method " + name);
final Method[] methods = searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods();
@@ -61,19 +65,56 @@ private static Method findMethod(Class> type, String name, Class>... paramet
boolean matches = true;
for (int i = 0; i < parameterTypes.length; i++) {
final Class> parameterType = parameterTypes[i];
- if (!PropertyUtils.getTypeOf(method.getParameterTypes()[i]).isAssignableFrom(PropertyUtils.getTypeOf(parameterType))) {
+ if (!doParamsMatchByAssignability(method.getParameterTypes()[i], PropertyUtils.getTypeOf(parameterType))) {
matches = false;
break;
}
}
if (matches) {
- return method;
+ matchingMethods.add(method);
}
}
}
searchType = searchType.getSuperclass();
}
+
+ if (matchingMethods.size() == 0) {
+ return null;
+ } else if (matchingMethods.size() == 1) {
+ return matchingMethods.get(0);
+ } else {
+ Method method = exactlyMatchingMethod(matchingMethods, parameterTypes);
+ if (method == null) {
+ return matchingMethods.get(matchingMethods.size() - 1);
+ } else {
+ return method;
+ }
+ }
+ }
+
+ private Method exactlyMatchingMethod(List methods, Class>[] parameterTypes) {
+ for (Method method : methods) {
+ boolean matches = true;
+ for (int i = 0; i < parameterTypes.length; i++) {
+ final Class> parameterType = parameterTypes[i];
+ if (!(doParamsMatchExactly(method.getParameterTypes()[i], PropertyUtils.getTypeOf(parameterType)))) {
+ matches = false;
+ break;
+ }
+ }
+ if (matches) {
+ return method;
+ }
+ }
return null;
}
+ protected boolean doParamsMatchByAssignability(Class> thisParam, Class> thatParam) {
+ return PropertyUtils.getTypeOf(thisParam).isAssignableFrom(thatParam);
+ }
+
+
+ protected boolean doParamsMatchExactly(Class> thisParam, Class> thatParam) {
+ return thisParam.getCanonicalName().equals(thatParam.getCanonicalName());
+ }
}
diff --git a/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/proxy/impl/resolvers/SignatureDataOperationResolverTest.java b/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/proxy/impl/resolvers/SignatureDataOperationResolverTest.java
index 7c11ab8c..418e1bff 100644
--- a/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/proxy/impl/resolvers/SignatureDataOperationResolverTest.java
+++ b/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/proxy/impl/resolvers/SignatureDataOperationResolverTest.java
@@ -8,7 +8,9 @@
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -30,6 +32,31 @@ public void setUp() throws Exception {
resolver = new SignatureDataOperationResolver(mappings);
}
+ @Test
+ public void testWeResolveTheCorrectMethod_whenMethodWithObjectParam_comesFirstInMethodList() throws Exception {
+ Method method = ProxiedClass.class.getMethod("somethingToAnObject", Iterable.class);
+ final DataStoreOperation, ?, ?> operation = resolver.resolve(method);
+
+ assertThat(operation, is(notNullValue()));
+ assertThat(operation, is(instanceOf(MethodInvocationDataStoreOperation.class)));
+ final MethodInvocationDataStoreOperation invocationOperation = (MethodInvocationDataStoreOperation) operation;
+ assertThat(invocationOperation.getInstance(), is(instanceOf(SuperInterface.class)));
+ assertThat(invocationOperation.getMethod(), is(SuperInterface.class.getMethod("somethingToAnObject", Iterable.class)));
+ }
+
+
+ @Test
+ public void testWeResolveTheCorrectMethod_whenMethodWithObjectParam_comesFirstInMethodList_andNotAnExactMatch() throws Exception {
+ Method method = ProxiedClass.class.getMethod("somethingToAnObject", Collection.class);
+ final DataStoreOperation, ?, ?> operation = resolver.resolve(method);
+
+ assertThat(operation, is(notNullValue()));
+ assertThat(operation, is(instanceOf(MethodInvocationDataStoreOperation.class)));
+ final MethodInvocationDataStoreOperation invocationOperation = (MethodInvocationDataStoreOperation) operation;
+ assertThat(invocationOperation.getInstance(), is(instanceOf(SuperInterface.class)));
+ assertThat(invocationOperation.getMethod(), is(SuperInterface.class.getMethod("somethingToAnObject", Iterable.class)));
+ }
+
@Test
public void testLookingForExactMatchViaInterface() throws Exception {
final DataStoreOperation, ?, ?> operation = resolver.resolve(ProxiedClass.class.getMethod("saySomething", String.class, Double.class));
diff --git a/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/sample/usecases/proxy/resolvers/ProxiedClass.java b/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/sample/usecases/proxy/resolvers/ProxiedClass.java
index 56f126e3..4f207801 100644
--- a/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/sample/usecases/proxy/resolvers/ProxiedClass.java
+++ b/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/sample/usecases/proxy/resolvers/ProxiedClass.java
@@ -1,5 +1,7 @@
package com.mmnaseri.utils.spring.data.sample.usecases.proxy.resolvers;
+import java.util.Collection;
+
/**
* @author Milad Naseri (mmnaseri@programmer.net)
* @since 1.0 (4/12/16, 6:36 PM)
@@ -16,4 +18,8 @@ public interface ProxiedClass {
void doSomething();
+ void somethingToAnObject(Iterable iterable);
+
+ void somethingToAnObject(Collection iterable);
+
}
diff --git a/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/sample/usecases/proxy/resolvers/SuperInterface.java b/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/sample/usecases/proxy/resolvers/SuperInterface.java
index d7b5fa4f..5ac328a7 100644
--- a/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/sample/usecases/proxy/resolvers/SuperInterface.java
+++ b/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/sample/usecases/proxy/resolvers/SuperInterface.java
@@ -6,8 +6,14 @@
*/
public interface SuperInterface {
+ void somethingToAnObject(Object object);
+
+ void somethingToAnObject(Iterable iterable);
+
+
void saySomething(CharSequence sequence, Double number);
void doSomething();
+
}
diff --git a/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/sample/usecases/proxy/resolvers/SuperInterfaceImpl.java b/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/sample/usecases/proxy/resolvers/SuperInterfaceImpl.java
index 11876f3e..6928dc99 100644
--- a/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/sample/usecases/proxy/resolvers/SuperInterfaceImpl.java
+++ b/spring-data-mock/src/test/java/com/mmnaseri/utils/spring/data/sample/usecases/proxy/resolvers/SuperInterfaceImpl.java
@@ -6,6 +6,16 @@
*/
public class SuperInterfaceImpl implements SuperInterface {
+ @Override
+ public void somethingToAnObject(Object object) {
+
+ }
+
+ @Override
+ public void somethingToAnObject(Iterable iterable) {
+
+ }
+
@Override
public void saySomething(CharSequence sequence, Double number) {
@@ -15,4 +25,5 @@ public void saySomething(CharSequence sequence, Double number) {
public void doSomething() {
}
+
}