mock instance is null after #Mock annotation - java

I try to run this test:
#Mock IRoutingObjHttpClient routingClientMock;
#Mock IRoutingResponseRepository routingResponseRepositoryMock;
#Test
public void testSendRoutingRequest() throws Exception {
CompleteRoutingResponse completeRoutingResponse = new CompleteRoutingResponse();
completeRoutingResponse.regression_latencyMillis = 500L;
Mockito.when(routingClientMock.sendRoutingRequest(any(RoutingRequest.class))).thenReturn(completeRoutingResponse);
RoutingObjHttpClientWithReRun routingObjHttpClientWithReRun = new RoutingObjHttpClientWithReRun
(routingClientMock, routingResponseRepositoryMock);
...
}
but I get NullPointerException for:
Mockito.when(routingClientMock.
what am i missing?

When you want to use the #Mock annotation you should use the MockitoJUnitRunner
#RunWith(MockitoJUnitRunner.class)
public class MockitoTest {
#Mock
private IRoutingObjHttpClient routingClientMock;
#Test
public void testSendRoutingRequest() throws Exception {
// ...
}
}
See also this tutorial.

Same problem can occur if you are using Junit5 since there is no more '#RunWith' annotation.
In this case you should annotate your class with:
#ExtendWith(MockitoExtension.class)
public class MyTestClass {
...
You should also import into your dependency (Maven - pom.xml):
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>

You have three options for activating the #Mock annotation: MockitoRule, MockitoJUnitRunner, MockitoAnnotations.initMocks(this). IMHO using the MockitoRule is the best one, because it lets you still choose another runner like e.g. Parameterized.
Use the MockitoRule
public class MockitoTest {
#Mock
private IRoutingObjHttpClient routingClientMock;
#Rule
public MockitoRule rule = MockitoJUnit.rule();
#Test
public void testSendRoutingRequest() throws Exception {
// ...
}
}
Use the MockitoJUnitRunner
#RunWith(MockitoJUnitRunner.class)
public class MockitoTest {
#Mock
private IRoutingObjHttpClient routingClientMock;
#Test
public void testSendRoutingRequest() throws Exception {
// ...
}
}
Call MockitoAnnotations.initMocks(this) explicitly.
This can be done in qn #Before method, in your own runner or in an own rule.
public class MockitoTest {
#Mock
private IRoutingObjHttpClient routingClientMock;
#Before
public void createMocks() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSendRoutingRequest() throws Exception {
// ...
}
}

If you use junit.jupiter with #ExtendWith(MockitoExtension.class) for test class but mocks are null, ensure that #Test annotation is imported from
import org.junit.jupiter.api.Test;
instead of org.junit.Test;

What solved this issue for me (combination of answers above and my own additions):
MockitoAnnotations.initMocks(this); in the #Before method
Test class must be public
Test methods must be public
import org.junit.Test; instead of import org.junit.jupiter.api.Test;
When doing command + N --> Test... in Intellij it generates (as a default at least) some boilerplate that did not work in my case.

For me, even after adding #RunWith(MockitoJUnitRunner.class) it was not working.
Turned out, I had made the silly mistake of importing #Test from
import org.junit.jupiter.api.Test;
instead of
import org.junit.Test;
After correcting it, it worked!

It can also be an import problem, so make sure you have the appropriate imported package.
For example, the "org.easymock" package also does have an annotation called #Mock, which of course, won't work with Mockito specific setup.

Add #ExtendWith(MockitoExtension.class) annotation to the test class and it should work given You are using Junit 5+ version.
If you are using older version of Junit use #RunWith(MockitoJUnitRunner.class) annotation.

You should use #RunWith(SpringJUnit4ClassRunner.class) at your class
You have to call MockitoAnnotations.initMocks(this); in #Before method

I had the problem that I declared #Mock MyClass myClass and then tried to mock a behaviour inside my #BeforeAll annotated method:
#Mock
private MyClass myClass;
...
#BeforeAll
public void init()
{
...
Mockito.when(myClass.something()).thenReturn("Not found")
...
}
Apparently init() was executed before the mock initialization of myClass, so myClass == null inside init().
The solution was to change the annotation from #BeforeAll to #BeforeEach.

Try to to check if the method that you are calling is a final method or not.
Mockito cannot mock the final method. https://github.com/mockito/mockito/wiki/FAQ

For me it worked when I added :
At class level:
#RunWith(MockitoJUnitRunner.class).
Inside class:
#Before
public void createMocks() {
MockitoAnnotations.initMocks(this);
}

Junit 5 with InjectMocks. Based on above suggestion https://stackoverflow.com/a/55616702/2643815
#ExtendWith(MockitoExtension.class)
public class MyClientTest {
#Mock
Environment environment;
#Mock
ClassCreator classCreator;
#InjectMocks
MyClient myClient;
#Test
public void mytest() {
myClient = new MyClient(environment, classCreator);
}
}

For me adding the annotation to the class:
#RunWith(MockitoJUnitRunner.class)
and modifying the version of Mockito solved this issue.
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>

I had the same issue, but I found updating my tests (which were originally written for JUnit 3 and used the legacy setUp() and tearDown() methods) to JUnit 4 and modern annotated fixture methods worked.
Additionally, if you're using the Rule:
#Rule public MockitoRule rule = MockitoJUnit.rule();
Make sure the rule is also on a public class or you will receive the message:
How did getFields return a field we couldn't access?

Found this solution in comments that worked for me. Do this for all the mocks you are creating.
You need to instantiate the routingClientMock e.g.
routingClientMock = Mockito.mock(RoutingObjHtttpClient.class);

My issue was that I was trying to mock an object which was final in my service. Just needed to remove final and it worked.

If you are also using PowerMock then
#RunWith(MockitoJUnitRunner.class)
can be replaced with
#RunWith(PowerMockRunner.class)
This will activate your #Mocks and enable the PowerMock functionality.

Related

Running Spring JUnit tests without #InjectMocks

I am trying to test a class (and it’s methods) using a JUnit test without the #InjectMocks annotation. The annotation will not work for me because the class I am attempting to test has class attributes that #InjectMocks will not create.
Here is what my functional class looks like:
(File path: src/main/java/com/mycompany/mypackage)
package com.mycompany.mypackage;
#Service
public class MyClass {
#Value(“${someString}”)
private String someString;
public printString() {
System.out.println(someString);
}
}
Here is what my testing class looks like:
(File path: src/test/java/com/mycompany/mypackage)
package com.mycompany.mypackage;
#RunWith(SpringJUnit4ClassRunner.class)
public class MyClassTest {
#InjectMocks
MyClass myClass
#Test
public testPrintString() {
myClass.printString()
}
}
I’ve tried to use #Autowired in the place of #InjectMocks to fully instantiate the MyClass bean, but this will not actually create a instance of MyClass, and I will get a null pointer exception whenever I try to use the ‘myClass’ variable in a test.
For my particular use case, using a constructor method is not a realistic alternative.
Any help would be awesome!
Try adding this to your test class to set the value using reflection:
import org.junit.Before;
import org.springframework.test.util.ReflectionTestUtils;
#Before
public void setup()
{
ReflectionTestUtils.setField(
myClass,"someString",
"SOME_VALUE", String.class);
}
If you do not want mock test, you should do as below.
// #RunWith(SpringJUnit4ClassRunner.class)
#RunWith(SpringRunner.class)
#SpringBootTest(classes = YourApplication.class) // YourApplication is your spring boot app main class used to import spring context
public class MyClassTest {
// #InjectMocks
#Autowired
MyClass myClass;
#Test
public void testPrintString() {
myClass.printString();
}
}

Simple Junit class is not calling the #Before method [duplicate]

I have the following code:
#BeforeClass
public static void setUpOnce() throws InterruptedException {
fail("LOL");
}
And various other methods that are either #Before, #After, #Test or #AfterClass methods.
The test doesn't fail on start up as it seems it should. Can someone help me please?
I have JUnit 4.5
The method is failing in an immediate call to setUp() which is annotated as #before.
Class def is :
public class myTests extends TestCase {
do NOT extend TestCase AND use annotations at the same time!
If you need to create a test suite with annotations, use the RunWith annotation like:
#RunWith(Suite.class)
#Suite.SuiteClasses({ MyTests.class, OtherTest.class })
public class AllTests {
// empty
}
public class MyTests { // no extends here
#BeforeClass
public static void setUpOnce() throws InterruptedException {
...
#Test
...
(by convention: class names with uppercase letter)
the method must be static and not directly call fail (otherwise the other methods won't be executed).
The following class shows all the standard JUnit 4 method types:
public class Sample {
#BeforeClass
public static void beforeClass() {
System.out.println("#BeforeClass");
}
#Before
public void before() {
System.out.println("#Before");
}
#Test
public void test() {
System.out.println("#Test");
}
#After
public void after() {
System.out.println("#After");
}
#AfterClass
public static void afterClass() {
System.out.println("#AfterClass");
}
}
and the ouput is (not surprisingly):
#BeforeClass
#Before
#Test
#After
#AfterClass
Make sure you imported #Test from the correct package.
Correct package: org.junit.Test
Incorrect pacakge: org.junit.jupiter.api.Test
Please note that this is a solution for: If your #Before, #Atter, etc did not get called at all.
Make sure that :
Your test class doesn't inherits from TestCase
The #BeforeClass method is static
You don't have more than one #BeforeClass method in test class hierarchy (only the most specialized #BeforeClass method will be executed)
Check your imports.
#Before
#After
#BeforeClass (this should be static)
#AfterClass (this should be static)
and #Test annotations should import from same path.
In order that the before annotated function will run , I had to do the following:
If you use Maven , add a dependency to Junit 4.11+:
<properties>
<version.java>1.7</version.java>
<version.log4j>1.2.13</version.log4j>
<version.mockito>1.9.0</version.mockito>
<version.power-mockito>1.4.12</version.power-mockito>
<version.junit>4.11</version.junit>
<version.power-mockito>1.4.12</version.power-mockito>
</properties>
and the dependency:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${version.junit}</version>
<scope>test</scope>
</dependency>
.
.
.
</dependencies>
Make sure your Junit Test class is not extending The TestCase class, since this will cause overlapping with Older version:
public class TuxedoExceptionMapperTest{
protected TuxedoExceptionMapper subject;
#Before
public void before() throws Exception {
subject = TuxedoExceptionMapper.getInstance();
System.out.println("Start");
MockitoAnnotations.initMocks(this);
}
}

Injecting mocks with Mockito does not work

I'm using Mockito to test my Spring project, but the #InjectMocks seems not working in injecting a mocked service into another Spring service(bean).
Here is my Spring service that I want to test:
#Service
public class CreateMailboxService {
#Autowired UserInfoService mUserInfoService; // this should be mocked
#Autowired LogicService mLogicService; // this should be autowired by Spring
public void createMailbox() {
// do mething
System.out.println("test 2: " + mUserInfoService.getData());
}
}
And below is the service that I want to mock:
#Service
public class UserInfoService {
public String getData() {
return "original text";
}
}
My test code is here:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/root-context.xml" })
public class CreateMailboxServiceMockTest {
#Mock
UserInfoService mUserInfoService;
#InjectMocks
#Autowired
CreateMailboxService mCreateMailboxService;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void deleteWithPermission() {
when(mUserInfoService.getData()).thenReturn("mocked text");
System.out.println("test 1: " + mUserInfoService.getData());
mCreateMailboxService.createMailbox();
}
}
but the result would like
test 1: mocked text
test 2: original text // I want this be "mocked text", too
it seems that the CreateMailboxService didn't get the mocked UserInfoService but using Spring's autowired bean.
Why is my #InjectMocks not working?
In my case, I had a similar issue when I worked with JUnit5
#ExtendWith(MockitoExtension.class)
class MyServiceTest {
...
#InjectMocks
MyService underTest;
#Test
void myMethodTest() {
...
}
underTest was null.
The cause of the problem was that I used #Test from JUnit4 package import org.junit.Test; instead JUnit5 import org.junit.jupiter.api.Test;
For those who stumbles on this thread and are running with JUnit 5 you need to replace
#RunWith(SpringJUnit4ClassRunner.class)
with
#ExtendWith(MockitoExtension.class)
#RunWith(JUnitPlatform.class)
Further reading here. Unfortunately there is no hint when executing the test cases with JUnit 5 using the old annotation.
You can create package level setter for mUserInfoService in CreateMailboxService class.
#Service
public class CreateMailboxService {
#Autowired UserInfoService mUserInfoService; // this should be mocked
#Autowired LogicService mLogicService; // this should be autowired by Spring
public void createMailbox() {
// do mething
System.out.println("test 2: " + mUserInfoService.getData());
}
void setUserInfoService(UserInfoService mUserInfoService) {
this.mUserInfoService = mUserInfoService;
}
}
Then, you can inject that mock in the test using the setter.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/root-context.xml" })
public class CreateMailboxServiceMockTest {
#Mock
UserInfoService mUserInfoService;
CreateMailboxService mCreateMailboxService;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
mCreateMailboxService = new CreateMailboxService();
mCreateMailboxService.setUserInfoService(mUserInfoService);
}
...
}
This way you can avoid problems with #InjectMocks and Spring annotations.
If you are trying to use the #Mock annotation for a test that relies directly on Spring injection, you may need to replace #Mock with #MockBean #Inject (both annotations), and #InjectMocks with #Inject. Using your example:
#MockBean
#Inject
UserInfoService mUserInfoService;
#Inject
CreateMailboxService mCreateMailboxService;
I had a pretty similar situation. I am writing it down just in case any reader is going through the same. In my case I found that the problem was that I was setting my injected variable as final in the local class.
Following your example, I had things like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/root-context.xml" })
public class CreateMailboxServiceMockTest {
#Mock
UserInfoService mUserInfoService;
#InjectMocks
CreateMailboxService mCreateMailboxService = new CreateMailboxService(mUserInfoService);
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void deleteWithPermission() {
...
}
}
But in this class I had it like this:
#Service
public class CreateMailboxService {
private final UserInfoService mUserInfoService; // it is NOT injecting Mocks just because it is final! (all ok with private)
private final LogicService mLogicService; // it is NOT injecting Mocks just because it is final! (all ok with private)
#Autowired
public CreateMailboxService(UserInfoService mUserInfoService, LogicService mLogicService) {
this.mUserInfoService = mUserInfoService;
this.mLogicService = mLogicService;
}
public void createMailbox() {
...
}
}
Just deleting the final condition, #InjectMocks problem was solved.
For those who are running with JUnit 5 you need to replace the #RunWith(SpringJUnit4ClassRunner.class) with #ExtendWith(MockitoExtension.class).
For further reading take a look here.
there is no need of #Autowired annotation when you inject in the test class. And use the mock for the method to get your mocked response as the way you did for UserInfoService.That will be something like below.
Mockito.when(mCreateMailboxService. getData()).thenReturn("my response");
You can use MockitoJUnitRunner to mock in unit tests.
Use #Mock annotations over classes whose behavior you want to mock.
Use #InjectMocks over the class you are testing.
Its a bad practice to use new and initialize classes (better to go for dependency injection) or to introduce setters for your injections. Using setter injection to set dependencies only for tests is wrong as production code should never be altered for tests.
#RunWith(MockitoJUnitRunner.class)
public class CreateMailboxServiceMockTest {
#Mock
UserInfoService mUserInfoService;
#InjectMocks
CreateMailboxService mCreateMailboxService;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
...
}

Mockito MissingMethodInvocation - Mocking call method on object that has not been initialized [duplicate]

There are many ways to initialize a mock object using MockIto.
What is best way among these ?
1.
public class SampleBaseTestCase {
#Before public void initMocks() {
MockitoAnnotations.initMocks(this);
}
#RunWith(MockitoJUnitRunner.class)
mock(XXX.class);
suggest me if there are any other ways better than these...
For the mocks initialization, using the runner or the MockitoAnnotations.initMocks are strictly equivalent solutions. From the javadoc of the MockitoJUnitRunner :
JUnit 4.5 runner initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks(Object) is not necessary. Mocks are initialized before each test method.
The first solution (with the MockitoAnnotations.initMocks) could be used when you have already configured a specific runner (SpringJUnit4ClassRunner for example) on your test case.
The second solution (with the MockitoJUnitRunner) is the more classic and my favorite. The code is simpler. Using a runner provides the great advantage of automatic validation of framework usage (described by #David Wallace in this answer).
Both solutions allows to share the mocks (and spies) between the test methods. Coupled with the #InjectMocks, they allow to write unit tests very quickly. The boilerplate mocking code is reduced, the tests are easier to read. For example:
#RunWith(MockitoJUnitRunner.class)
public class ArticleManagerTest {
#Mock private ArticleCalculator calculator;
#Mock(name = "database") private ArticleDatabase dbMock;
#Spy private UserProvider userProvider = new ConsumerUserProvider();
#InjectMocks private ArticleManager manager;
#Test public void shouldDoSomething() {
manager.initiateArticle();
verify(database).addListener(any(ArticleListener.class));
}
#Test public void shouldDoSomethingElse() {
manager.finishArticle();
verify(database).removeListener(any(ArticleListener.class));
}
}
Pros: The code is minimal
Cons: Black magic. IMO it is mainly due to the #InjectMocks annotation. With this annotation "you loose the pain of code" (see the great comments of #Brice)
The third solution is to create your mock on each test method.
It allow as explained by #mlk in its answer to have "self contained test".
public class ArticleManagerTest {
#Test public void shouldDoSomething() {
// given
ArticleCalculator calculator = mock(ArticleCalculator.class);
ArticleDatabase database = mock(ArticleDatabase.class);
UserProvider userProvider = spy(new ConsumerUserProvider());
ArticleManager manager = new ArticleManager(calculator,
userProvider,
database);
// when
manager.initiateArticle();
// then
verify(database).addListener(any(ArticleListener.class));
}
#Test public void shouldDoSomethingElse() {
// given
ArticleCalculator calculator = mock(ArticleCalculator.class);
ArticleDatabase database = mock(ArticleDatabase.class);
UserProvider userProvider = spy(new ConsumerUserProvider());
ArticleManager manager = new ArticleManager(calculator,
userProvider,
database);
// when
manager.finishArticle();
// then
verify(database).removeListener(any(ArticleListener.class));
}
}
Pros: You clearly demonstrate how your api works (BDD...)
Cons: there is more boilerplate code. (The mocks creation)
My recommandation is a compromise. Use the #Mock annotation with the #RunWith(MockitoJUnitRunner.class), but do not use the #InjectMocks :
#RunWith(MockitoJUnitRunner.class)
public class ArticleManagerTest {
#Mock private ArticleCalculator calculator;
#Mock private ArticleDatabase database;
#Spy private UserProvider userProvider = new ConsumerUserProvider();
#Test public void shouldDoSomething() {
// given
ArticleManager manager = new ArticleManager(calculator,
userProvider,
database);
// when
manager.initiateArticle();
// then
verify(database).addListener(any(ArticleListener.class));
}
#Test public void shouldDoSomethingElse() {
// given
ArticleManager manager = new ArticleManager(calculator,
userProvider,
database);
// when
manager.finishArticle();
// then
verify(database).removeListener(any(ArticleListener.class));
}
}
Pros: You clearly demonstrate how your api works (How my ArticleManager is instantiated). No boilerplate code.
Cons: The test is not self contained, less pain of code
There is now (as of v1.10.7) a fourth way to instantiate mocks, which is using a JUnit4 rule called MockitoRule.
#RunWith(JUnit4.class) // or a different runner of your choice
public class YourTest
#Rule public MockitoRule rule = MockitoJUnit.rule();
#Mock public YourMock yourMock;
#Test public void yourTestMethod() { /* ... */ }
}
JUnit looks for subclasses of TestRule annotated with #Rule, and uses them to wrap the test Statements that the Runner provides. The upshot of this is that you can extract #Before methods, #After methods, and even try...catch wrappers into rules. You can even interact with these from within your test, the way that ExpectedException does.
MockitoRule behaves almost exactly like MockitoJUnitRunner, except that you can use any other runner, such as Parameterized (which allows your test constructors to take arguments so your tests can be run multiple times), or Robolectric's test runner (so its classloader can provide Java replacements for Android native classes). This makes it strictly more flexible to use in recent JUnit and Mockito versions.
In summary:
Mockito.mock(): Direct invocation with no annotation support or usage validation.
MockitoAnnotations.initMocks(this): Annotation support, no usage validation.
MockitoJUnitRunner: Annotation support and usage validation, but you must use that runner.
MockitoRule: Annotation support and usage validation with any JUnit runner.
See also: How JUnit #Rule works?
1. Using MockitoAnnotations.openMocks():
The MockitoAnnotations.initMock() method in Mockito 2 is deprecated and replaced with MockitoAnnotations.openMocks() in Mockito 3. The MockitoAnnotations.openMocks() method returns an instance of AutoClosable which can be used to close the resource after the test. Below is an example using MockitoAnnotations.openMocks().
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
class MyTestClass {
AutoCloseable openMocks;
#BeforeEach
void setUp() {
openMocks = MockitoAnnotations.openMocks(this);
// my setup code...
}
#Test
void myTest() {
// my test code...
}
#AfterEach
void tearDown() throws Exception {
// my tear down code...
openMocks.close();
}
}
2. Using #ExtendWith(MockitoExtension.class):
As of JUnit5 #RunWith has been removed. Below is an example using #ExtendWith:
#ExtendWith(MockitoExtension.class)
class MyTestClass {
#BeforeEach
void setUp() {
// my setup code...
}
#Test
void myTest() {
// my test code...
}
#AfterEach
void tearDown() throws Exception {
// my tear down code...
}
}
A little example for JUnit 5 Jupiter, the "RunWith" was removed you now need to use the Extensions using the "#ExtendWith" Annotation.
#ExtendWith(MockitoExtension.class)
class FooTest {
#InjectMocks
ClassUnderTest test = new ClassUnderTest();
#Spy
SomeInject bla = new SomeInject();
}
MockitoAnnotations & the runner have been well discussed above, so I'm going to throw in my tuppence for the unloved:
XXX mockedXxx = mock(XXX.class);
I use this because I find it a little bit more descriptive and I prefer (not out right ban) unit tests not to use member variables as I like my tests to be (as much as they can be) self contained.
There is a neat way of doing this.
If it's an Unit Test you can do this:
#RunWith(MockitoJUnitRunner.class)
public class MyUnitTest {
#Mock
private MyFirstMock myFirstMock;
#Mock
private MySecondMock mySecondMock;
#Spy
private MySpiedClass mySpiedClass = new MySpiedClass();
// It's gonna inject the 2 mocks and the spied object per reflection to this object
// The java doc of #InjectMocks explains it really well how and when it does the injection
#InjectMocks
private MyClassToTest myClassToTest;
#Test
public void testSomething() {
}
}
EDIT: If it's an Integration test you can do this(not intended to be used that way with Spring. Just showcase that you can initialize mocks with diferent Runners):
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("aplicationContext.xml")
public class MyIntegrationTest {
#Mock
private MyFirstMock myFirstMock;
#Mock
private MySecondMock mySecondMock;
#Spy
private MySpiedClass mySpiedClass = new MySpiedClass();
// It's gonna inject the 2 mocks and the spied object per reflection to this object
// The java doc of #InjectMocks explains it really well how and when it does the injection
#InjectMocks
private MyClassToTest myClassToTest;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSomething() {
}
}
In te lastest version of Mockito the method MockitoAnnotations.initMocks is deprecated
Preferred way is use
MockitoJUnitRunner or MockitoRule for JUnit4
MockitoExtension for JUnit5
MockitoTestNGListener for TestNG
If you can not use dedicated runner/extension you can use MockitoSession
The other answers are great and contain more detail if you want/need them.
In addition to those, I would like to add a TL;DR:
Prefer to use
#RunWith(MockitoJUnitRunner.class)
If you cannot (because you already use a different runner), prefer to use
#Rule public MockitoRule rule = MockitoJUnit.rule();
Similar to (2), but you should not use this anymore:
#Before public void initMocks() {
MockitoAnnotations.initMocks(this);
}
If you want to use a mock in just one of the tests and don't want to expose it to other tests in the same test class, use
X x = mock(X.class)
(1) and (2) and (3) are mutually exclusive.
(4) can be used in combination with the others.

How to AutoWire spring beans when using Mockito and Junit?

I am trying to set up my class to be used in Junit.
However when I try to do the below I get an error.
Current Test Class:
public class PersonServiceTest {
#Autowired
#InjectMocks
PersonService personService;
#Before
public void setUp() throws Exception
{
MockitoAnnotations.initMocks(this);
assertThat(PersonService, notNullValue());
}
//tests
Error:
org.mockito.exceptions.base.MockitoException:
Cannot instantiate #InjectMocks field named 'personService'
You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : null
How can I fix this?
You are not mocking anything in your code. #InjectMocks sets a class where a mock will be injected.
Your code should look like this
public class PersonServiceTest {
#InjectMocks
PersonService personService;
#Mock
MockedClass myMock;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
Mockito.doReturn("Whatever you want returned").when(myMock).mockMethod;
}
#Test()
public void testPerson() {
assertThat(personService.method, "what you expect");
}
Another solution is to use #ContextConfiguration annotation with static inner configuration class like so:
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class PersonServiceTest {
#Autowired
PersonService personService;
#Before
public void setUp() throws Exception {
when(personService.mockedMethod()).thenReturn("something to return");
}
#Test
public void testPerson() {
assertThat(personService.method(), "what you expect");
}
#Configuration
static class ContextConfiguration {
#Bean
public PersonService personService() {
return mock(PersonService.class);
}
}
}
Anyway, you need to mock something that the method you want to test uses inside to get desired behaviour of that method. It doesn't make sense to mock the service you're testing.
You're misunderstanding the purpose of the mock here.
When you mock out a class like this, you are pretending as if it's been injected into your application. That means you don't want to inject it!
The solution to this: set up whatever bean you were intending to inject as #Mock, and inject them into your test class via #InjectMocks.
It's unclear where the bean you want to inject is since all you have is the service defined, but...
#RunWith(MockitoJUnitRunner.class);
public class PersonServiceTest {
#Mock
private ExternalService externalSvc;
#InjectMocks
PersonService testObj;
}
If I am not mistaken...the thumb rule is you cannot use both together..you either run unit test cases with using MockitojunitRunner or SpringJUnitRunner you cannot use both of them together.

Categories

Resources