From c7b56e022669975fe1af47636477bea8ee64c181 Mon Sep 17 00:00:00 2001
From: Tomas Poledny <saljacky@gmail.com>
Date: Sat, 15 May 2021 23:43:20 +0200
Subject: [PATCH] Add method name check for generic methods Expectations

---
 .../invocation/ExpectedInvocation.java        |  8 +++-
 .../mockit/CapturingImplementationsTest.java  | 48 +++++++++++++++++++
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/main/src/mockit/internal/expectations/invocation/ExpectedInvocation.java b/main/src/mockit/internal/expectations/invocation/ExpectedInvocation.java
index 1dea784f2..bef98071a 100644
--- a/main/src/mockit/internal/expectations/invocation/ExpectedInvocation.java
+++ b/main/src/mockit/internal/expectations/invocation/ExpectedInvocation.java
@@ -113,7 +113,7 @@ private boolean isMatchingGenericMethod(@Nullable Object mock, @Nonnull String i
             if (mockedClass != instance.getClass()) {
                GenericTypeReflection typeReflection = new GenericTypeReflection(mockedClass, null);
                GenericSignature parsedSignature = typeReflection.parseSignature(genericSignature);
-               return parsedSignature.satisfiesSignature(invokedMethod);
+               return parsedSignature.satisfiesSignature(invokedMethod) && isMatchingMethodName(invokedMethod);
             }
          }
       }
@@ -137,6 +137,12 @@ private boolean isMatchingMethod(@Nonnull String invokedMethod) {
       return isReturnTypeOfRecordedMethodAssignableToReturnTypeOfInvokedMethod(invokedMethod, returnTypeStartPos);
    }
 
+   private boolean isMatchingMethodName(@Nonnull String invokedMethod) {
+      int methodNameEndPos = invokedMethod.indexOf('(');
+      String methodName = invokedMethod.substring(0, methodNameEndPos + 1);
+      return getMethodNameAndDescription().startsWith(methodName);
+   }
+
    // Returns -1 if the method names or parameters are different.
    private int getReturnTypePosition(@Nonnull String invokedMethod) {
       String recordedMethod = getMethodNameAndDescription();
diff --git a/main/test/mockit/CapturingImplementationsTest.java b/main/test/mockit/CapturingImplementationsTest.java
index 4d1942fd0..5f5b5c7d0 100644
--- a/main/test/mockit/CapturingImplementationsTest.java
+++ b/main/test/mockit/CapturingImplementationsTest.java
@@ -196,22 +196,26 @@ public void captureClassWhichImplementsCapturedBaseInterfaceAndExtendsUnrelatedB
    static class Base<T> {
       T doSomething() { return null; }
       void doSomething(T t) { System.out.println("test");}
+      T doSomethingReturn(T t) { return t;}
    }
 
    static final class Impl extends Base<Integer> {
       @Override Integer doSomething() { return 1; }
       @Override void doSomething(Integer i) {}
+      @Override Integer doSomethingReturn(Integer t) { return null;}
    }
 
    @Test
    public void captureImplementationsOfGenericType(@Capturing final Base<Integer> anyInstance) {
       new Expectations() {{
          anyInstance.doSomething(); result = 2;
+         anyInstance.doSomethingReturn(0);
          anyInstance.doSomething(0);
       }};
 
       Base<Integer> impl = new Impl();
       int i = impl.doSomething();
+      impl.doSomethingReturn(0);
       impl.doSomething(0);
 
       assertEquals(2, i);
@@ -263,4 +267,48 @@ public void captureLibraryClassImplementingInterfaceFromAnotherLibrary(@Capturin
 
       new Verifications() {{ mock.contextInitialized(null); }};
    }
+
+   static class BaseGenericReturnTypes {
+      Class<?> methodOne() {return null;}
+      Class<?> methodTwo() {return null;}
+   }
+   static class SubGenericReturnTypes extends BaseGenericReturnTypes {}
+
+   @Test
+   public void captureMethodWithGenericReturnTypes(@Capturing final BaseGenericReturnTypes mock) {
+      new Expectations () {{
+         mock.methodOne();
+         result = BaseGenericReturnTypes.class;
+         times = 1;
+
+         mock.methodTwo();
+         result = SubGenericReturnTypes.class;
+         times = 1;
+      }};
+      SubGenericReturnTypes subBaseGenericReturnTypes = new SubGenericReturnTypes();
+      assertEquals(BaseGenericReturnTypes.class, subBaseGenericReturnTypes.methodOne());
+      assertEquals(SubGenericReturnTypes.class, subBaseGenericReturnTypes.methodTwo());
+   }
+
+   static class BaseR {
+     void foo() {};
+     void bar() {};
+   }
+
+   static class SubR extends BaseR {}
+
+   @Test
+   public void captureR(@Capturing final BaseR mock) {
+      new Expectations () {{
+         mock.foo();
+         times = 1;
+
+         mock.bar();
+         times = 1;
+      }};
+     SubR subR = new SubR();
+     subR.foo();
+     subR.bar();
+   }
+
 }
\ No newline at end of file