Issue 489 in mockito: @InjectMocks and @Spy cannot be used together when object initialized by mockito

891 views
Skip to first unread message

moc...@googlecode.com

unread,
Apr 17, 2014, 8:49:58 PM4/17/14
to mocki...@googlegroups.com
Status: New
Owner: ----
Labels: Type-Defect Priority-Medium

New issue 489 by yuanju...@gmail.com: @InjectMocks and @Spy cannot be used
together when object initialized by mockito
http://code.google.com/p/mockito/issues/detail?id=489

What steps will reproduce the problem?
1. use @InjectMocks and @Spy annotation on the same object A.
2. use @InjectMocks annotation on object B to inject A.
3. after initMocks(this), the reference of B within A is null.

code example:
@InjectMocks
@Spy
A a;

@InjectMocks
B b;

What is the expected output? What do you see instead?
The expect result is I have a spy object A inside B after initMocks(). But
inside B I have A refers to null.

What version of the product are you using? On what operating system?
Mockito 1.9.5, windows 7.

Please provide any additional information below.
The following code will be working as expected:
@InjectMocks
@Spy
A a = new A();

@InjectMocks
B b;

I think the problem might be in the class SpyAnnotationEngine's method
process(Class<?> context, Object testInstance), as it will ignore the
initialization of field annotated by both @Spy and @InjectMocks.

Although the javadoc says "If the field is also annotated with the
compatible @InjectMocks then the field will be ignored, The injection
engine will handle this specific case." In my test it seems the injection
engine doesn't handle this case after all.

--
You received this message because this project is configured to send all
issue notifications to this address.
You may adjust your notification preferences at:
https://code.google.com/hosting/settings

moc...@googlecode.com

unread,
Apr 21, 2014, 1:19:32 PM4/21/14
to mocki...@googlegroups.com

Comment #1 on issue 489 by brice.du...@gmail.com: @InjectMocks and @Spy
cannot be used together when object initialized by mockito
http://code.google.com/p/mockito/issues/detail?id=489

Remember that mockito is not an injection framework, so it won't handle
every case. Anyway I just wonder why the spy A would need InjectMocks, does
it needs other mocks ? `@Spy A a;` should be enough.

If so my I would say there's something wrong in your test. For me adding
multiple INjectMocks is confusing on the code that should be tested,
because there's several level of mocks. And anyway if A needs collaborators
for some reason, I wouldn't use a mockito for this object creation.

moc...@googlecode.com

unread,
May 21, 2014, 1:20:50 PM5/21/14
to mocki...@googlegroups.com

Comment #2 on issue 489 by fernando...@gmail.com: @InjectMocks and @Spy
cannot be used together when object initialized by mockito
http://code.google.com/p/mockito/issues/detail?id=489

Hi guys, I report the same issue. When a field is annotated with
@InjectMocks, if it also has a @Spy annotation, the latter is ignored.

The scenario is the following:
I want to test the class TestClass, which needs a DataFilter instance

class TestClass{
@Autowired
DataFilter filter;
}

we don't want to mock the DataFilter for many reasons, and it needs another
DataRetrieval in order to work

class DataFilter {
@Autowired
DataRetrieval dataProvider;
}

We want to mock the DataRetrieval inside the DataFilter, so we need to
annotate DataFilter with InjectMocks. At the same time, DataFilter is just
something we need in order to run our test on TestClass, so DataFilter must
be a @Spy as well.

@Mock
DataRetrieval retrieval;

@InjectMocks
@Spy
DataFilter filter;

@InjectMocks
TestClass classToBeTested;


If I annoted DataFilter with Spy only I would get TestClass with the not
null field "filter" as excepted, but the filter is not able to work because
it doesn't have any DataRetrieval
If I annoted DataFilter with InjectMocks only I would a working instance of
the filter, and the TestClass with filter=null

If I put both annotations instead, surprisingly, I have the same outcome of
the lonely InjectMocks annotation

thanks for your attention

moc...@googlecode.com

unread,
Jun 27, 2014, 12:32:44 PM6/27/14
to mocki...@googlegroups.com
Updates:
Status: WontFix
Labels: -Type-Defect Type-Enhancement

Comment #3 on issue 489 by brice.du...@gmail.com: @InjectMocks and @Spy
cannot be used together when object initialized by mockito
http://code.google.com/p/mockito/issues/detail?id=489

This would require mockito to build a graph of dependencies. And this is
the work of a dependency injection framework which mockito isn't and
shouldn't become.

If you are desperate to support such cases, please make a pull request so
we can evaluate the feature.

Thanks for your interest.

Cheers,
Brice

moc...@googlecode.com

unread,
Dec 17, 2014, 4:55:30 PM12/17/14
to mocki...@googlegroups.com

Comment #4 on issue 489 by dmwallace.nz: @InjectMocks and @Spy cannot be
used together when object initialized by mockito
https://code.google.com/p/mockito/issues/detail?id=489

I'd like to vote for this feature. One of my current tests is breaking
because of this not working. Basically, I'm testing a class A with a whole
load of dependencies B, C, D; and B also has dependencies E, F etc. I need
to stub just one method of B, but otherwise have B working as normal.

So I want to mock C, D, E, F and spy B. I then want to inject E and F into
B, and then inject B, C, D into A. So B requires @InjectMocks and @Spy.
But this seems to be explicitly disabled by a line in SpyAnnotationEngine,
that says if (field.isAnnotationPresent(Spy.class)
&& !field.isAnnotationPresent(InjectMocks.class)) {.

I'm not sure what the reason for this is. It seems an odd thing to
disable. This is NOT about Mockito potentially becoming a dependency
injection framework - it's about being able to mock and spy what we need to
mock and spy.

What would be the impact of changing the offending line in
SpyAnnotationEngine to if (field.isAnnotationPresent(Spy.class)) { ?

moc...@googlecode.com

unread,
Jan 23, 2015, 7:58:31 AM1/23/15
to mocki...@googlegroups.com

Comment #5 on issue 489 by grodecki...@gmail.com: @InjectMocks and @Spy
cannot be used together when object initialized by mockito
https://code.google.com/p/mockito/issues/detail?id=489

Actually, @Spy and @InjectMocks worked toghether in previous mockito
release, i.e. 1.8.5
so this restriction comes with 1.9 or 1.10 major release, does it??

moc...@googlecode.com

unread,
Jan 29, 2015, 1:25:38 PM1/29/15
to mocki...@googlegroups.com

Comment #6 on issue 489 by liqiang: @InjectMocks and @Spy cannot be used
together when object initialized by mockito
https://code.google.com/p/mockito/issues/detail?id=489

Use powermock's Whitebox.setInternalState as a workaround

moc...@googlecode.com

unread,
Feb 14, 2015, 3:12:51 PM2/14/15
to mocki...@googlegroups.com

Comment #7 on issue 489 by brice.du...@gmail.com: @InjectMocks and @Spy
cannot be used together when object initialized by mockito
https://code.google.com/p/mockito/issues/detail?id=489

tl;dr Not gonna happen, what is being asked is actually the beginning of an
real dependency injection library, which is not the spirit of @InjectMocks,
if for some reason a bad design imposes to have two level of injections in
the test, then :

1. create a dedicated factory method / builder in the test utils
2. good design can be measured by a low PITA metric, if the PITA is too
high then a refactoring is needed
3. this may not be a unit test at all, but an integration test in which
case why would we want mockito short hand mock injection as part of it

moc...@googlecode.com

unread,
Feb 15, 2015, 3:34:05 PM2/15/15
to mocki...@googlegroups.com

Comment #8 on issue 489 by mail.mac...@gmail.com: @InjectMocks and @Spy
cannot be used together when object initialized by mockito
https://code.google.com/p/mockito/issues/detail?id=489

Checking the codebase I found a test case
WrongSetOfAnnotationsTest.shouldNotAllowSpyAndInjectMock() which, I guess,
was supposed to cover Brice's explanation. The test passes because the
MockitoException is thrown, but it's thrown for different reason: the test
tries to instantiate an interface (List). The test was there at list since
2010, so I think the behavior could have been basically forgotten.
So, although I find Brice's explanation convincing, I still think the
exception should be thrown in that case, informing of wrong Mockito usage.

moc...@googlecode.com

unread,
Feb 15, 2015, 4:06:09 PM2/15/15
to mocki...@googlegroups.com

Comment #9 on issue 489 by mail.mac...@gmail.com: @InjectMocks and @Spy
cannot be used together when object initialized by mockito
https://code.google.com/p/mockito/issues/detail?id=489

I let myself to raise another issue for above:
https://github.com/mockito/mockito/issues/169

moc...@googlecode.com

unread,
Feb 15, 2015, 7:42:17 PM2/15/15
to mocki...@googlegroups.com

Comment #10 on issue 489 by brice.du...@gmail.com: @InjectMocks and @Spy
cannot be used together when object initialized by mockito
https://code.google.com/p/mockito/issues/detail?id=489

Thx, let's continue the discussion on the PR then, it's much more
comfortable on GH ;)
Reply all
Reply to author
Forward
0 new messages