Constructor injection is not working -- Mockito always asks to get a default constructor

2,267 views
Skip to first unread message

Markus Karg

unread,
Feb 16, 2013, 5:42:36 AM2/16/13
to moc...@googlegroups.com
I want to use constructor injection (inject B-mock into A), so I did (using Java 7)...
 
public final class A {
     public A(B b);
}
 
interface B {
}
 
@RunWith(MockitoJunitRunner.class) public MyTest {
    @Mock B b;
    @InjectMocks A a;
    @Test ... {}
}
 
When I start JUni 4.10, Mockito 1.9.5 says that it cannot find the default constructor. This is correct, as I do not have one, and as I do not want Mockito to call it -- as I want to use constructor injection (hence need a non-default-constructor).
 
What to do?
 
If I simply add the default constructor, Mockito calls that one, hence does not inject into the non-default constructor.
 
I am totally desparate, please help! :-)
 
 

Marcin Zajączkowski

unread,
Feb 16, 2013, 7:14:35 AM2/16/13
to moc...@googlegroups.com
On 2013-02-16 11:42, Markus Karg wrote:
> I want to use constructor injection (inject B-mock into A), so I did (using
> Java 7)...
>
> public final class A {
> public A(B b);
> }
>
> interface B {
> }
>
> @RunWith(MockitoJunitRunner.class) public MyTest {
> @Mock B b;
> @InjectMocks A a;
> @Test ... {}
> }
>
> When I start JUni 4.10, Mockito 1.9.5 says that it cannot find the default
> constructor. This is correct, as I do not have one, and as I do not want
> Mockito to call it -- as I want to use constructor injection (hence need a
> non-default-constructor).

I suspected that final in class A could make some problems, but I'm
unable to reproduce this with Mockito 1.9.5, JUnit 4.10, OpenJDK 7.
Could you provide a complete test case with testing classes?

Marcin



>
> What to do?
>
> If I simply add the default constructor, Mockito calls that one, hence does
> not inject into the non-default constructor.
>
> I am totally desparate, please help! :-)
>
>
>


--
http://blog.solidsoft.info/ - Working code is not enough

Markus Karg

unread,
Feb 16, 2013, 9:16:09 AM2/16/13
to moc...@googlegroups.com
I found the cause of the problem meanwhile, and how to reproduce (and solve) it even without Java 7, Maven or Eclipse. It has nothing to do with "final".
 
Modify the above class A so that it has a second constructor and looks like this:
 
public final class A {
     public A(int i);
     public A(B b);
}
 
Now you will get the mentioned complaint from Mockito that it cannot find the default constructor!
 
Workaround: Change the sequence of both constructors (so it is A(B b) followed by A(int i), or simply add one useless argument in the signature of A(B b, Object ignored). Both will make the test succeed.
 
Cause: Misleading description in Mockito API JavaDocs! It says that "the biggest" constructor is chosen, which is right if there is on... but it does not say what to do if there is no single biggest constructor. As this sample proofs, it just picks the first-in-sequence. And, what JavaDocs also do not say: If the first-of-biggest is not injectable (like here), it wants to use the default constructor (which here is missing, hence the message), not the next-in-sequence (hence: not the biggest anymore).
 
I'll file an issue with the Mockito tracker to enhance the JavaDocs, so everybody knows about this two dirty tricks.
 
Thanks
-Markus

Eric Lefevre-Ardant

unread,
Feb 17, 2013, 10:21:12 AM2/17/13
to moc...@googlegroups.com
Hm... indeed, I could reproduce that.

Agreed, the documentation could use some polishing.

Also, I don't see why we couldn't make the code smarter and make it figure out the right constructor, at least in cases like this. A topic for a future Hackergarten !


--
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.
 
 

Brice Dutheil

unread,
Feb 17, 2013, 4:28:22 PM2/17/13
to moc...@googlegroups.com
Yes some stuff could be ironed. You could also patch the code too ;)

Also note that the order of methods or constructor at reflection time is not guaranteed in the JLS, so I wouldn't rely on it. I'd rather say it's not supported, in the way you proposed, or make the code to work.

However I don't want to make the injection code too smart because, it can lead to unwanted behavior or injection.

Anyway thanks for reporting this :)



-- Brice
Reply all
Reply to author
Forward
0 new messages