Mockito. doNothing() Keeps Returning Null Pointer Exception
I Know I Should Not Be Testing Void Methods Like This, but I Am Just Testing Mockito. doNothing() as of Now with a Simple Example. My Service Class: @Service...
I know I should not be testing void methods like this, but I am just testing Mockito.doNothing() as of now with a simple example.
My Service class:
@Service
public class Service{
@Autowired
private Consumer<String, String> kafkaConsumer;
public void clearSubscribtions(){
kafkaConsumer.unsubscribe();
}
}
My Test class:
@MockBean
private Consumer<String, String> kafkaConsumer;
@Test
public void testClearSubscriptions() {
Service service = new Service();
Mockito.doNothing().when(kafkaConsumer).unsubscribe();
service.clearSubscriptions();
}
The test keeps failing with a null pointer exception. When I debugged it, it goes into the clearSubscription method of the service class, and there on the line of kafkaConsumer.unsubscribe(), kafkaConsumer is null. But I mocked the consumer, why is it throwing null pointer exception and I should be skipping over that method, right?
Edit: All the declarations of the class:
@Autowired
private Consumer<String, String> kafkaConsumer;
@Autowired
private Service2 service2;
private final Object lock = new Object();
private static Logger logger = LoggerFactory.getLogger(Service.class);
private HashMap<String, String> subscribedTopics = new HashMap<>();
Figured out what was wrong, I needed to auto wire the service
1 Answer
You are instantiating a new service Service service = new Service(); but from what I can see you are never injecting the mock bean into the new service.
Here is a sample of what I think you could do if you are using mockito only and dont need to instantiate a spring container (used a single class for ease of example dont do this in actual code):
package com.sbp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@RunWith(MockitoJUnitRunner.class) // run with mockitos runner so annotations are processed
public class MyServiceTest {
public interface Consumer<T, R> {
public void unsubscribe();
}
@Service
public class KafkaConsumer implements Consumer<String, String> {
@Override
public void unsubscribe() {
}
}
@Service
public class MyService {
@Autowired
private Consumer<String, String> kafkaConsumer;
public void clearSubscriptions() {
kafkaConsumer.unsubscribe();
}
}
@Mock // tell mockito that this is a mock class - it will instantiate for you
private Consumer<String, String> kafkaConsumer;
@InjectMocks // tell mockito to inject the above mock into the class under test
private MyService service = new MyService();
@Test
public void testClearSubscriptions() {
service.clearSubscriptions();
Mockito.verify(kafkaConsumer, Mockito.times(1)).unsubscribe();
}
}
If you need an example via Spring using MockBean or without and dependencies, let me know and I can post.
UPDATED: adding sample using spring junit runner and using spring boot's mockbean annotation
package com.sbp;
import com.sbp.MyServiceTest.TestContext.MyService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class) // run with spring
@SpringBootTest(classes = MyServiceTest.TestContext.class) // make it a spring boot test so @MockBean annotation is processed, provide a dummy test context class
public class MyServiceTest {
public interface Consumer<T, R> {
public void unsubscribe();
}
@Configuration
public static class TestContext {
@Service
public class KafkaConsumer implements Consumer<String, String> {
@Override
public void unsubscribe() {
}
}
@Service
public class MyService {
@Autowired
private Consumer<String, String> kafkaConsumer;
public void clearSubscriptions() {
kafkaConsumer.unsubscribe();
}
}
}
@MockBean // this will create a mockito bean and put it in the application context in place of the Kafka consumer bean defined in the TestContext class
private Consumer<String, String> kafkaConsumer;
@Autowired // inject the bean from the application context that is wired with the mock bean
private MyService myService;
@Test
public void testClearSubscriptions() {
myService.clearSubscriptions();
Mockito.verify(kafkaConsumer, Mockito.times(1)).unsubscribe();
}
}