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
11 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(); }
} 6