我知道我不应该测试这样的 void 方法,但我现在只是用一个简单的例子来测试 Mockito.doNothing() 。
我的服务类别:
@Service
public class Service{
@Autowired
private Consumer<String, String> kafkaConsumer;
public void clearSubscribtions(){
kafkaConsumer.unsubscribe();
}
}
我的测试类(class):
@MockBean
private Consumer<String, String> kafkaConsumer;
@Test
public void testClearSubscriptions() {
Service service = new Service();
Mockito.doNothing().when(kafkaConsumer).unsubscribe();
service.clearSubscriptions();
}
测试一直失败并出现空指针异常。当我调试它时,它进入服务类的clearSubscription方法,在kafkaConsumer.unsubscribe()这一行,kafkaConsumer为null。但我 mock 了消费者,为什么它会抛出空指针异常,我应该跳过该方法,对吗?
编辑: 该类的所有声明:
@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<>();
找出问题所在,我需要自动连接服务
最佳答案
您正在实例化一个新服务Service service = new Service();
,但据我所知,您从未将模拟bean注入(inject)到新服务中。
以下是我认为如果您仅使用mockito并且不需要实例化spring容器时可以执行的示例(为了便于示例而使用单个类,请勿在实际代码中执行此操作):
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();
}
}
如果您需要通过 Spring 使用 MockBean 或不使用依赖项的示例,请告诉我,我可以发布。
更新:使用 spring junit runner 并使用 spring boot 的mockbean注释添加示例
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();
}
}
关于java - Mockito.doNothing() 不断返回空指针异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40952380/