Repository: mockito/mockito
Issue: InjectMocks injects mock into wrong field

Using `1.10.19`.

When using `@InjectMocks` on some Android `TextView`s, the mock is injected into the wrong field.

We have two fields, `txtGateView` & `txtNextStep` in a class, and our test mocks out `txtNextStep`, then tried to inject. This field is injected wrong, see screenshot.

![image](https://cloud.githubusercontent.com/assets/1404810/7410003/4f200580-ef2b-11e4-9c39-7a699dc4fefa.png)

From our quick testing, the name `txtNextView` doesn't matter, that can be changed. But both `txtGateView` and `txtGateLabel` messed things up. If we mock out both fields, it works correctly.

Testproject: https://github.com/SimenB/emptyandroid

I don't know if it's because it's Android, but it was easiest for me to create a minimal test from existing code.


Issue comments:
@SimenB Maybe txtNextStep TextView Class Mocking the aneunge not work properly?
A bug or would not even be on @InjectMocks features?

I have answered a similar question on Stackoverflow and you can find my investigations at http://stackoverflow.com/a/29954211/2761676

@JeremybellEU Yeah, that seems to be the same thing.
While it explains _why_ it happens, I still consider it to be a bug...

Not a bug, it is just something that was left off.

Thanks @JeremybellEU, I'll look into your PR. Note the merge is gonna happen in 2.x line (which is beta and subject to important changes, both internally and API wise).

After I commented I realised I probably knew how to fix it, so I hope the PR is useful =]. Looking forward to Mockito 2.0.


Pull request review comments:

Patch that resolved the issue:
diff --git a/src/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java b/src/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java
index 67126afd95..c17f961c5a 100644
--- a/src/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java
+++ b/src/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java
@@ -111,7 +111,7 @@ private boolean injectMockCandidates(Class<?> awaitingInjectionClazz, Set<Object
     private boolean injectMockCandidatesOnFields(Set<Object> mocks, Object instance, boolean injectionOccurred, List<Field> orderedInstanceFields) {
         for (Iterator<Field> it = orderedInstanceFields.iterator(); it.hasNext(); ) {
             Field field = it.next();
-            Object injected = mockCandidateFilter.filterCandidate(mocks, field, instance).thenInject();
+            Object injected = mockCandidateFilter.filterCandidate(mocks, field, orderedInstanceFields, instance).thenInject();
             if (injected != null) {
                 injectionOccurred |= true;
                 mocks.remove(injected);
diff --git a/src/org/mockito/internal/configuration/injection/filter/FinalMockCandidateFilter.java b/src/org/mockito/internal/configuration/injection/filter/FinalMockCandidateFilter.java
index 7bd70735f7..aebf6f71e4 100644
--- a/src/org/mockito/internal/configuration/injection/filter/FinalMockCandidateFilter.java
+++ b/src/org/mockito/internal/configuration/injection/filter/FinalMockCandidateFilter.java
@@ -10,6 +10,7 @@
 
 import java.lang.reflect.Field;
 import java.util.Collection;
+import java.util.List;
 
 /**
  * This node returns an actual injecter which will be either :
@@ -20,7 +21,7 @@
  * </ul>
  */
 public class FinalMockCandidateFilter implements MockCandidateFilter {
-    public OngoingInjecter filterCandidate(final Collection<Object> mocks, final Field field, final Object fieldInstance) {
+    public OngoingInjecter filterCandidate(final Collection<Object> mocks, final Field field, List<Field> fields, final Object fieldInstance) {
         if(mocks.size() == 1) {
             final Object matchingMock = mocks.iterator().next();
 
diff --git a/src/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java b/src/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java
index 7a2c08781e..81a168b491 100644
--- a/src/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java
+++ b/src/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java
@@ -6,13 +6,14 @@
 
 import java.lang.reflect.Field;
 import java.util.Collection;
+import java.util.List;
 
 public interface MockCandidateFilter {
 
     OngoingInjecter filterCandidate(
             Collection<Object> mocks,
             Field fieldToBeInjected,
-            Object fieldInstance
+            List<Field> fields, Object instance
     );
 
 }
diff --git a/src/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java b/src/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java
index 7023e66ba2..abc5d67b45 100644
--- a/src/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java
+++ b/src/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java
@@ -12,23 +12,50 @@
 import java.util.List;
 
 public class NameBasedCandidateFilter implements MockCandidateFilter {
-    private final MockCandidateFilter next;
-    private final MockUtil mockUtil = new MockUtil();
+	private final MockCandidateFilter next;
+	private final MockUtil mockUtil = new MockUtil();
 
-    public NameBasedCandidateFilter(MockCandidateFilter next) {
-        this.next = next;
-    }
+	public NameBasedCandidateFilter(MockCandidateFilter next) {
+		this.next = next;
+	}
 
-    public OngoingInjecter filterCandidate(Collection<Object> mocks, Field field, Object fieldInstance) {
-        List<Object> mockNameMatches = new ArrayList<Object>();
-        if(mocks.size() > 1) {
-            for (Object mock : mocks) {
-                if (field.getName().equals(mockUtil.getMockName(mock).toString())) {
-                    mockNameMatches.add(mock);
-                }
-            }
-            return next.filterCandidate(mockNameMatches, field, fieldInstance);
-        }
-        return next.filterCandidate(mocks, field, fieldInstance);
-    }
+	public OngoingInjecter filterCandidate(Collection<Object> mocks,
+			Field field, List<Field> fields, Object fieldInstance) {
+		List<Object> mockNameMatches = new ArrayList<Object>();
+		if (mocks.size() > 1) {
+			for (Object mock : mocks) {
+				if (field.getName().equals(mockUtil.getMockName(mock).toString())) {
+					mockNameMatches.add(mock);
+				}
+			}
+			return next.filterCandidate(mockNameMatches, field, fields,
+					fieldInstance);
+			/*
+			 * In this case we have to check whether we have conflicting naming
+			 * fields. E.g. 2 fields of the same type, but we have to make sure
+			 * we match on the correct name.
+			 * 
+			 * Therefore we have to go through all other fields and make sure
+			 * whenever we find a field that does match its name with the mock
+			 * name, we should take that field instead.
+			 */
+		} else if (mocks.size() == 1) {
+			String mockName = mockUtil.getMockName(mocks.iterator().next())
+					.toString();
+
+			for (Field otherField : fields) {
+				if (!otherField.equals(field)
+						&& otherField.getType().equals(field.getType())
+						&& otherField.getName().equals(mockName)) {
+
+					return new OngoingInjecter() {
+						public Object thenInject() {
+							return null;
+						}
+					};
+				}
+			}
+		}
+		return next.filterCandidate(mocks, field, fields, fieldInstance);
+	}
 }
diff --git a/src/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java b/src/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java
index dd79991a65..ce7a349fa7 100644
--- a/src/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java
+++ b/src/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java
@@ -17,7 +17,7 @@ public TypeBasedCandidateFilter(MockCandidateFilter next) {
         this.next = next;
     }
 
-    public OngoingInjecter filterCandidate(Collection<Object> mocks, Field field, Object fieldInstance) {
+    public OngoingInjecter filterCandidate(Collection<Object> mocks, Field field, List<Field> fields, Object fieldInstance) {
         List<Object> mockTypeMatches = new ArrayList<Object>();
         for (Object mock : mocks) {
             if (field.getType().isAssignableFrom(mock.getClass())) {
@@ -25,6 +25,6 @@ public OngoingInjecter filterCandidate(Collection<Object> mocks, Field field, Ob
             }
         }
 
-        return next.filterCandidate(mockTypeMatches, field, fieldInstance);
+        return next.filterCandidate(mockTypeMatches, field, fields, fieldInstance);
     }
 }


Test patch:
diff --git a/test/org/mockitousage/annotation/MockInjectionUsingSetterOrPropertyTest.java b/test/org/mockitousage/annotation/MockInjectionUsingSetterOrPropertyTest.java
index bd49f3adee..c6eb915851 100644
--- a/test/org/mockitousage/annotation/MockInjectionUsingSetterOrPropertyTest.java
+++ b/test/org/mockitousage/annotation/MockInjectionUsingSetterOrPropertyTest.java
@@ -4,6 +4,9 @@
  */
 package org.mockitousage.annotation;
 
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
 import org.fest.assertions.Assertions;
 import org.junit.Before;
 import org.junit.Test;
@@ -28,6 +31,7 @@ public class MockInjectionUsingSetterOrPropertyTest extends TestBase {
     @InjectMocks private BaseUnderTesting baseUnderTest = new BaseUnderTesting();
     @InjectMocks private SubUnderTesting subUnderTest = new SubUnderTesting();
     @InjectMocks private OtherBaseUnderTesting otherBaseUnderTest = new OtherBaseUnderTesting();
+    @InjectMocks private OtherSuperUnderTesting otherSuperUnderTesting = new OtherSuperUnderTesting();
 
     private BaseUnderTesting baseUnderTestingInstance = new BaseUnderTesting();
     @InjectMocks private BaseUnderTesting initializedBase = baseUnderTestingInstance;
@@ -40,6 +44,8 @@ public class MockInjectionUsingSetterOrPropertyTest extends TestBase {
     @Mock private List list;
     @Mock private Set histogram1;
     @Mock private Set histogram2;
+    @Mock private A candidate2;
+    
     @Spy private TreeSet searchTree = new TreeSet();
     private MockUtil mockUtil = new MockUtil();
 
@@ -103,6 +109,13 @@ public void shouldInjectSpies() {
         assertSame(searchTree, otherBaseUnderTest.getSearchTree());
     }
     
+    @Test
+	public void shouldInsertFieldWithCorrectNameWhenMultipleTypesAvailable() {
+		MockitoAnnotations.initMocks(this);
+		assertNull(otherSuperUnderTesting.candidate1);
+		assertNotNull(otherSuperUnderTesting.candidate2);
+	}
+    
     @Test
     public void shouldInstantiateInjectMockFieldIfPossible() throws Exception {
         assertNotNull(notInitializedBase);
@@ -168,4 +181,15 @@ public Set getHistogram2() {
             return histogram2;
         }
     }
+    
+    static class OtherSuperUnderTesting {
+		private A candidate1;
+
+		private A candidate2;
+	}
+
+	interface A {
+	}
+
+    
 }