Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Autowire combined with @InjectMocks

I have a Spring boot project which has a suite of unit tests which use mockito's @InjectMocks to both instantiate the class being tested and inject any mocks which may be present into it.

In other words if I have this

@InjectMocks MyClass myClass;

Then I do not need

MyClass myClass = New MyClass();
or @Autowired MyClass myClass;

Until now this setup worked fine.

However more recently it has become necessary to have access to the projects spring boot properties when running tests. This means it has been necessary to use the SpringBoot task runner inside tests so that any instances of @Autowire (including those which instantiate the Environment class) work.

I discovered that if @InjectMocks is used to instantiate a class then any instances of @Autowired inside the class do not work (the object they should create is null). This means no Environment class and no access to Spring properties.

Instead i have to add @Autowired to the @InjectMocks annotation

so this

@InjectMocks MyClass myClass;

becomes this

@Autowired
@InjectMocks MyClass myClass;

My question is simple. Is there anything wrong with doing this? Does it double instantiate myClass or do anything that may causes glitches

like image 913
megaman Avatar asked Feb 08 '17 09:02

megaman


People also ask

Can we use InjectMocks and Autowired together?

Here if you see @Autowired @InjectMocks are used together and what it will do is inject the mocked class (which is SomeRepository in our case) and Autowired annotation adds any other dependency which the class might have. The last thing you need to do is create a Setter for SomeRepository object in your actual class.

What is the difference between @InjectMocks and @mock?

@Mock is used to create mocks that are needed to support the testing of the class to be tested. @InjectMocks is used to create class instances that need to be tested in the test class.

What is the use of @InjectMocks annotation?

@InjectMocks is the Mockito Annotation. It allows you to mark a field on which an injection is to be performed. Injection allows you to, Enable shorthand mock and spy injections.

Should I use @resource or @autowired?

@Resource is quite similar to @Autowired and @Inject, but the main difference is the execution paths taken to find out the required bean to inject. @Resource will narrow down the search first by name then by type and finally by Qualifiers (ignored if match is found by name).


1 Answers

I think you're mixing up the annotations that belong to spring and those that belong to Mockito.

When just running your web application, @Autowired will provide your class with a particular dependency. This way you don't have to do any manual creation of objects with the new keyword. But at runtime, it is only the spring annotations that are at play. The mockito annotations are not meant for this use case.

When you're running tests, it's the other way around. Now the spring annotations won't do anything, it's the mockito annotations that are working. @InjectMocks will tell mockito: "Anything that I provided with @Mock and that's needed by this class, just stick it in there". It will do that even if you didn't put @Autowired on that field. Mockito doesn't care about spring annotations.

For your question: I don't see a use case where you would put @Autowired and @InjectMocks in the same place. Use spring annotations in your application's logic and mockito annotations in your tests.

I know the answer is quite abstract, but so is your question. To get some more specific help you should provide a minimal, complete and verifiable example.

like image 127
HerrSubset Avatar answered Sep 28 '22 05:09

HerrSubset