5

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

megaman
  • 1,035
  • 1
  • 14
  • 21
  • What test runner did you use that allowed you to use `@InjectMocks` and `@Autowired` simultaneously (the class you mention in the `@RunWith` annotation you add to the test class itself). – shinvu Sep 25 '19 at 06:49

1 Answers1

6

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.

Community
  • 1
  • 1
HerrSubset
  • 99
  • 1
  • 5