Constructor injection in unit tests

585 views
Skip to first unread message

Richard Paul

unread,
Jul 12, 2011, 3:47:24 PM7/12/11
to mockito
I've written up some thoughts on wiring up collaborators (in my
example Mockito mocks) in unit tests using constructor injection
(based on examples in Growing Object Oriented Software Guided by
Tests).

public class ItemCheckerTest {

private final ItemFetcher itemFetcher = mock(ItemFetcher.class);
private final Notifier notifier = mock(Notifier.class);
private final ItemChecker itemChecker = new ItemChecker(itemFetcher,
notifier);

// tests ...
}

What are people's thoughts on this approach for making test setup
simple and gaining the benefits of constructor injection (avoiding
circular dependencies in production code & objects initialised without
all required collaborators). In the comments Faith brings up
@InjectMocks as an alternative but I feel constructor injection is a
cleaner more robust approach.

http://www.rapaul.com/2011/07/10/constructor-injection-unit-tests/

Keen to hear your thoughts.

Brice Dutheil

unread,
Jul 12, 2011, 8:11:56 PM7/12/11
to moc...@googlegroups.com
Hi Richard,

Your article is a good reading, and I personnally couldn't agree more with constructor injection.
Imho the GOOS book is one of the must read book.

Anyway, it's coming along the next release of mockito through the @InjectMocks.


-- 
Bryce



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


Szczepan Faber

unread,
Jul 13, 2011, 10:13:40 AM7/13/11
to moc...@googlegroups.com
Yeah, I tend to like constructor injection myself.

I'm doing quite a lot of groovy these days. Many times I still create
explicit constructors even though groovy has language support for
map-based constructors & has getters & setters for free.

If I'm keen on forcing constructor injection from tests in java, I
would do something like:

class MyTest {
@Mock Foo foo
@Mock Bar bar
Service service = new Service(foo, bar);

// then the test methods

Since JUnit instantiates fields per each test method we don't need
@Before method. That's pretty much what you have in your blog :)

Cheers!

--
Szczepan Faber
Principal engineer@gradleware
Lead@mockito

Brice Dutheil

unread,
Jul 13, 2011, 11:07:22 AM7/13/11
to moc...@googlegroups.com
Hi,

Unfortunately as it's a new instance for each test, Java will instantiate fields before any work happens on annotations (in current JUnit/Mockito code).
So new Service(foo, bar) will be executed as new Service(null, null).

Which is why, imho, constructor injection via @InjectMocks will come handy in the next release.



Regards,


-- 
Bryce

Szczepan Faber

unread,
Jul 13, 2011, 11:17:22 AM7/13/11
to moc...@googlegroups.com
Ouch, I forgot about it :)

Richard Paul

unread,
Jul 13, 2011, 4:41:39 PM7/13/11
to mockito
Given you can create the mocks and wire them up all inline there isn't
any need for a special @InjectMocks annotation. The following does
just that:

private ItemFetcher itemFetcher = mock(ItemFetcher.class);
private Notifier notifier = mock(Notifier.class);
private ItemChecker itemChecker = new ItemChecker(itemFetcher,
notifier);

Or does the @InjectMocks annotation provide something else? If not it
seems like an unnecessary addition to the otherwise nicely opinionated
Mockito API.

BTW: I created an equivalent example using Spock and Groovy at
http://meetspock.appspot.com/?id=33001 which uses the same approach
(explicit constructor) if you are interested Szczepan.

On Jul 13, 4:17 pm, Szczepan Faber <szcze...@gmail.com> wrote:
> Ouch, I forgot about it :)
>
>
>
>
>
>
>
>
>
> On Wed, Jul 13, 2011 at 5:07 PM, Brice Dutheil <brice.duth...@gmail.com> wrote:
> > Hi,
>
> > Unfortunately as it's a new instance for each test, Java will instantiate
> > fields before any work happens on annotations (in current JUnit/Mockito
> > code).
> > So new Service(foo, bar) will be executed as new Service(null, null).
>
> > Which is why, imho, constructor injection via @InjectMocks will come handy
> > in the next release.
>
> > Regards,
>
> > --
> > Bryce
>
> > On Wed, Jul 13, 2011 at 16:13, Szczepan Faber <szcze...@gmail.com> wrote:
>
> >> Yeah, I tend to like constructor injection myself.
>
> >> I'm doing quite a lot of groovy these days. Many times I still create
> >> explicit constructors even though groovy has language support for
> >> map-based constructors & has getters & setters for free.
>
> >> If I'm keen on forcing constructor injection from tests in java, I
> >> would do something like:
>
> >> class MyTest {
> >>  @Mock Foo foo
> >>  @Mock Bar bar
> >>  Service service = new Service(foo, bar);
>
> >>  // then the test methods
>
> >> Since JUnit instantiates fields per each test method we don't need
> >> @Before method. That's pretty much what you have in your blog :)
>
> >> Cheers!
>
> >> On Wed, Jul 13, 2011 at 2:11 AM, Brice Dutheil <brice.duth...@gmail.com>
> >> wrote:
> >> > Hi Richard,
> >> > Your article is a good reading, and I personnally couldn't agree more
> >> > with
> >> > constructor injection.
> >> > Imho the GOOS book is one of the must read book.
> >> > Anyway, it's coming along the next release of mockito through the
> >> > @InjectMocks.
>
> >> > --
> >> > Bryce
>
> >> > On Tue, Jul 12, 2011 at 21:47, Richard Paul <richard.a.p...@gmail.com>

Szczepan Faber

unread,
Jul 13, 2011, 4:57:01 PM7/13/11
to moc...@googlegroups.com
> Or does the @InjectMocks annotation provide something else? If not it
> seems like an unnecessary addition to the otherwise nicely opinionated
> Mockito API.

It's not a killer feature, no doubt. Yet, you don't even know how many
people are excited about it :) I'm OK with multiple ways of achieving
the goal so the annotations do not bother me too much. Annotations
tend to stick out better in a test and hence (arguably) readability
increases a bit.

@InjectMocks falls back to reflection which is something some people appreciate.

Cheers!

Reply all
Reply to author
Forward
0 new messages