Proposition: new annotation to inject real objects

4,132 views
Skip to first unread message

Michal Domagala

unread,
Apr 6, 2013, 4:19:01 PM4/6/13
to mockito
I often use the following pattern

@Stateless class A{
@EJB private B b;
@EJB private C c;
(...)
}

There is no setter in class A, application server injects everything.

I would like to test A with the following pattern:

@Mock C c;
@Real B b;
@InjectMockAndReal A a;
(...)
Actually, if I want have test where class A use both real objects and
mocks, I have to add setB(B b) to class A
But method setB(B b) will be used only by tests. I don't want testing
code in the class!.

I'm inspired by Unitils (http://unitils.org/tutorial-inject.html) and
@InjectIntoByType

My proposition may have some weakness, for example how to inject D
into B if B looks like
@Stateless class B{
@EJB private D d;
}

Anyway, I would like to have an option to inject something else than
mock is simple way

Michal Domagala




Igor Czechowski

unread,
Apr 6, 2013, 6:19:25 PM4/6/13
to moc...@googlegroups.com
You may want to try @Spy annotation as it should do the work you.

@Mock C c;
@Spy B b = new B();

@InjectMocks
A a = new A();

Cheers,
  Igor



Michal Domagala




--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.
To post to this group, send email to moc...@googlegroups.com.
Visit this group at http://groups.google.com/group/mockito?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.



Michal Domagala

unread,
Apr 7, 2013, 2:59:52 PM4/7/13
to mockito
Indeed, Spy annotation should be a solution. I was focused on spying
functions of the Spy and I missed that it could be used for simple
injection.

Although Spy solves simple case, it may be not enough for more complex
cases(how to inject Spy into Spy?). Probably I will be back when I
clarify my expectations

Thank you, Igor
Michał Domagała


On Apr 7, 12:19 am, Igor Czechowski <iczechow...@gmail.com> wrote:
> You may want to try @Spy annotation as it should do the work you.
>
> @Mock C c;
> @Spy B b = new B();
>
> @InjectMocks
> A a = new A();
>
> Cheers,
>   Igor
>

Mirko Raner

unread,
Dec 16, 2014, 12:43:04 PM12/16/14
to moc...@googlegroups.com
Sorry for reviving such an old conversation, but I still see a need for such an annotation.
The main problem is that @Spy cannot be used to inject final classes, such as Strings.
How complicated would it be to add such an annotation?

David Wallace

unread,
Dec 17, 2014, 3:12:54 PM12/17/14
to moc...@googlegroups.com
I've said this before.  Mockito is a mocking framework, not an all-purpose dependency injection tool.  Providing a means to inject things that aren't spies or mocks seems to be outside the scope of what Mockito should be concerned with.  I feel we shouldn't be turning Mockito into something that sings, dances and makes coffee.  I can certainly see the arguments in favour of such a feature, but if it came to a vote, mine would be against.

Visit this group at http://groups.google.com/group/mockito.
For more options, visit https://groups.google.com/d/optout.

KARR, DAVID

unread,
Dec 18, 2014, 10:59:39 AM12/18/14
to moc...@googlegroups.com

Perhaps a reasonable way to characterize this scope would be “mocking support for testing”.  I don’t get the impression that the OP is talking about anything else.  I would certainly discourage using Mockito as an “all-purpose dependency injection tool”, but I don’t think that’s what we’re talking about here.  If we’re talking about making it easier to write tests, using convenient annotations using expected conventions, then I think this is reasonable to talk about.

David Wallace

unread,
Dec 18, 2014, 3:37:24 PM12/18/14
to moc...@googlegroups.com
I'm actually starting to think it would be worthwhile suggesting some kind of injection mechanism to the JUnit and TestNG teams, if nobody else has done so already.  I accept that we sometimes need to inject things that aren't mocks, and even if we were doing no mocking at all, there are cases where we'd want to do this.  So maybe the whole @Xxx / @InjectXxx mechanism would sit better there.  And if we can get it added to JUnit and TestNG, we could deprecate @InjectMocks out of Mockito; which in my opinion would be a good thing too.

Szczepan Faber

unread,
Dec 18, 2014, 4:48:06 PM12/18/14
to moc...@googlegroups.com
All arguments are valid. There are pros and cons of having injection
feature in Mockito. For good or bad this feature is included in
Mockito. Growing it to support more use cases (that are reasonable and
useful) is unavoidable.

Perhaps this part of code should be extracted out to a separate
library 'mockito-inject' that could have a separate release cadence.

Cheers!
Szczepan Faber
Core dev@gradle; Founder@mockito

David Wallace

unread,
Dec 18, 2014, 4:50:06 PM12/18/14
to moc...@googlegroups.com
Or just "injectito", since it's not specifically about mocks any more.

Marcin Grzejszczak

unread,
Dec 18, 2014, 4:57:55 PM12/18/14
to moc...@googlegroups.com
I have written such code (in Groovy however - https://github.com/marcingrzejszczak/spock-subjects-collaborators-extension) that does what @InjectMock does + more hideous stuff like injecting fields into superclass' private fields. 

The question remains whether such tools should actually exist. They help people to test bad code, but what should be done is in fact proper refactoring of that code. Instead people inject mocks into private fields via reflection instead of having proper constructors.

David Wallace

unread,
Dec 18, 2014, 5:01:45 PM12/18/14
to moc...@googlegroups.com
You speak of "bad code", but most often, it's code that's written for Spring.  A lot of Spring stuff has endless autowired stuff, and if you don't want to go and recreate your Spring application context in the course of  your test, you're stuck with needing a way to inject things.  So a decent test framework should include such a mechanism, whether it satisfies the purists or not.

Marcin Grzejszczak

unread,
Dec 18, 2014, 5:05:07 PM12/18/14
to moc...@googlegroups.com
Actually yes and no :) You can create Spring code that has beans having normal constructors and autowire the fields via constructors. In fact this is what Spring recommends. Do not autowire via fields, autowire via constructor or setters (optional dependencies).

People do autowire on fields because it's easier for them. After some time they have 20 @AUtowired fields and they don't even notice that the class does too much. Instead if you have a constructor that has 5 object having injected then you start to ask yourself whether everything is fine.

Pozdrawiam / Best regards,
Marcin Grzejszczak

David Wallace

unread,
Dec 18, 2014, 5:09:40 PM12/18/14
to moc...@googlegroups.com
You're right, of course, Marcin.  However, try joining a big Spring project partway through, where there are a dozen developers, all writing components without "big constructors", that each do a lot of work.  It's a hard sell to get the team to refactor everything in the way you'd like them to; as opposed to just doing something like @InjectMocks.  

Perhaps the PowerMock team would be interested in doing some feature like this.  Their raison d'etre seems to be to facilitate the testing of badly-written code.

Marcin Grzejszczak

unread,
Dec 18, 2014, 5:12:39 PM12/18/14
to moc...@googlegroups.com
Dawid - I am in such a project :D And of course without @InjectMocks it would be terribly difficult to live :) Of course we are doing the boy scout rule but it's difficult.

IMO this "injectito" makes sense a separate project but it should be stated as like with PowerMock that it's a mean towards writing good code (of course majority of people will ignore this part ;)).

Pozdrawiam / Best regards,
Marcin Grzejszczak

Mirko Raner

unread,
Dec 18, 2014, 5:57:28 PM12/18/14
to moc...@googlegroups.com
Just to provide some more background information: I'm working on a project that's not using Spring, but heavily relies on dependency injection (HK2, in our case).
To keep some of the tests (especially the true unit tests) lightweight and fast, we don't always want to fire up DI, and we occasionally use @Mock/@InjectMocks as a convenient way to inject the dependencies. In some cases, the dependencies include String values, which we can't inject right now.
I think that very good arguments were made for both the pro and the con side of adding this kind of non-mock injection feature. It really depends on the overall philosophy/roadmap that you envision for Mockito. One thing I know for sure: Dependency Injection (may it be Guice, HK2, Dagger, or Spring) is pretty much a standard on most modern projects, and there is a need to support it during testing. It would be great to have injection support as part of Mockito, or as a separate add-on, if that fits better into the overall vision for Mockito.


--
You received this message because you are subscribed to a topic in the Google Groups "mockito" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mockito/dyHxTCli0YI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mockito+u...@googlegroups.com.

Russell Bateman

unread,
Dec 18, 2014, 6:35:54 PM12/18/14
to moc...@googlegroups.com
Here's the tail wagging the dog...

A few years ago, I ripped Spring completely out of our (server) application precisely because of not having injection when I got to the tests. I didn't want two different DI approaches going on, so I went with a service-locator pattern that worked for both JUnit, Mockito and the production code. (It's true that DI was all we were using Spring for and I was exasperated by the sheer weight of its JARs and the impact it was having on performance early on in the project.)

Witold Szczerba

unread,
Dec 19, 2014, 2:16:24 AM12/19/14
to moc...@googlegroups.com
David is right, but maybe it could be better if the "bad code" will stick to Spring... So, Szczepan said about an option to move out the extra stuff to external library. How about creating an SPI for mockito injections? The "mockito-inject" could be a gateway for different integrations, like Spring or Guice or some custom one?

Last time I used a DI in my application - it was Guice. So I have created a JUnit runner which injects objects into tests using Guice. Something like "mockito-inject" could be excellent option to make it simpler, so there would be no need to create custom runners and, but the way, it could work with mocks. Also, one could pick the DI framework of their choice. David could pick the Spring based one and all the Spring trickery would work out of the box...

Does it make sense?

Regards,
Witold Szczerba

Rogerio

unread,
Feb 8, 2015, 11:47:54 AM2/8/15
to moc...@googlegroups.com
Maybe you guys will be mad at me for mentioning a competing product, but the "@Tested(fullyInitialized = true)" annotation in JMockit provides the desired functionality for JUnit and TestNG. I developed it for my needs in integration testing a Java EE 7 web app, where real (or mocked) JPA EntityManager's and EJB's need to be injected into private fields using standard CDI/JavaEE annotations; it supports Spring's @Autowired as well.

So, I would say this is definitely a feature worth having.

Brice Dutheil

unread,
Feb 8, 2015, 12:33:12 PM2/8/15
to moc...@googlegroups.com
Mockito already offers some extension points, to change the mockmaker, the stack trace filter, allow one to change the injection code make sense.

On the topic, injecting other values that are already initialized may be worth it. But constructing a graph of dependency is never gonna happen inside Mockito ; whatever DI framework, it's not the role of a mocking framework in unit test and if it's about integration tests then why using Mockito short-hand injection.

I always felt that one can guess the code quality with the pita factor, especially when writing / maintaining unit tests, if the framework hides this pain then I'll probably dismiss the need for a refactoring.



-- Brice

Meang Akira Tanaka

unread,
Jun 29, 2015, 4:53:14 AM6/29/15
to moc...@googlegroups.com
Hi Brice

I had a similar challenges with injecting real values and I thought at first hand to write a new runner for Junit, however I did discover that one can change the annotation engine of the mockito runner by implementing a customized MockitoConfiguration,

however I am indoubt if that is the right way as the configuration has to be implemented in a specific class (org.mockito.configuration.MockitoConfiguration)

Do you know if that is the appropriate way or is there an alternative approach that is more correct?

For the discussion in this thread I have implemented an annotation engine, which can inject real values based on the @Mock and @InjectMocks annotations. (https://github.com/mat013/mockitoinjection)

Another annotation for injecting real values should most likely be used rather than @InjectMock,

br

Meang
Reply all
Reply to author
Forward
0 new messages