java - Mockito.doNothing() 不断返回空指针异常

标签 java unit-testing mockito

我知道我不应该测试这样的 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/

相关文章:

java - (Java) 错误 : constructor MinimaxThread in class MinimaxThread cannot be applied to given types

unit-testing - 将TDD用于库/API代码和将BDD用作集成测试有意义吗?

java - 如果方法在使用 Powermock 进行单元测试期间调用,如何有效验证方法

java - 如何解决 Mockito 参数匹配问题?

java - 为 scala akka webservice 编写测试用例

java - 如果用户创建成功,StackMob 会显示 Toast

java - 如何正确使用 UUID.fromString 方法?

java - Mockito 能否根据方法调用时的值来验证参数?

java - 如何实现一个以字符串为键和值的 HashMap ,它是一个要执行的函数

node.js - 用 Jest 模拟间接依赖