【问题标题】:GridFsTemplate NullPointerException in Service Unit Test Class (Tech Stack: Spring Data / Spring Boot / Micro Service / Mongodb )服务单元测试类中的 GridFsTemplate NullPointerException(技术栈:Spring Data / Spring Boot / Micro Service / Mongodb )
【发布时间】:2016-06-24 13:32:27
【问题描述】:

我正在开发一个 Spring Boot 应用程序。 服务方法使用在服务中自动装配的 GridFsTemplate 将 PDF 上传到 mongodb 存储库。 此文件上传服务方法通过邮递员休息客户端按预期工作。 但是,当我尝试运行单元测试时;调用相同的服务方法,SpringData GridFsTemplate 未初始化(在 MongoDB 中,您可以使用 GridFS 存储二进制文件)。这会导致 org.springframework.data.mongodb.gridfs.GridFsTemplate.store(...) 抛出 NullPointerException。 拜托,你能帮忙吗,我已经被困了几天了。

下面是我的服务实现:

@Service
public final class UploadServiceImpl implements UploadService {

    @Autowired
    private SequenceRepository sequenceDao;

    @Autowired (required = true)
    private GridFsTemplate gridFsTemplate;

    @Override
    public Long uploadFile(Invoice uploadedInvoice) {

        ByteArrayInputStream byteArrayInputStream = null;

        if (checkContentType(invoiceInfo.getContentType())) {

            invoiceInfo.setPaymentID(sequenceDao.getNextSequenceId(INVOICE_UPLOAD_SEQ_KEY));
            byteArrayInputStream = new ByteArrayInputStream(uploadedInvoice.getFileContent());

//Error thrown is java.lang.NullPointerException: null, where     gridFsTemplate is null and basically autowire does not work when test is     run.

                GridFSFile gridFSUploadedFile=     gridFsTemplate.store(byteArrayInputStream, invoiceInfo.getFileName(),     invoiceInfo.getContentType(), invoiceInfo);
                return  1l;

        } else {
            return 2l;
        }
    }
### 下面是我的服务单元测试类
@RunWith(MockitoJUnitRunner.class)
@ContextConfiguration
public class UploadServiceTest {

    @Mock
    private SequenceRepository sequenceRepositoryMock;

    @Autowired
    private GridFsTemplate gridFsTemplateMock;

    @Mock
    private Invoice invoiceMock;

    @InjectMocks
    private static UploadService uploadService = new UploadServiceImpl();

    DBObject fileMetaData = null;

    DB db = null;
    Jongo jongo = null;

 @Before
    public void setUp() throws Exception {
        db = new Fongo("Test").getDB("Database");
        jongo = new Jongo(db);
    }

@Test
    public void testUploadFile() {

        //test 1
        Long mockPaymentNo = new Long(1);
        Mockito.when(sequenceRepositoryMock.getNextSequenceId(INVOICE_SEQUENCE)).thenReturn(mockPaymentNo);
        assertEquals(mockPaymentNo, (Long) sequenceRepositoryMock.getNextSequenceId(INVOICE_SEQUENCE));

        //test 2

        Invoice dummyInvoice = getDummyInvoice();
        InvoiceInfo dummyInvoiceInfo = dummyInvoice.getInvoiceInfo();

        MongoCollection invoicesCollection = jongo.getCollection("invoices");

        assertNotNull(invoicesCollection.save(dummyInvoiceInfo));
        assertEquals(1, invoicesCollection.save(dummyInvoiceInfo).getN());

        System.out.println("TEST 2 >>>>>>>>>>>>>>>>>> "+ uploadService);


        //test 3 : The following line is the cause of the exception, the service method is called but the GridFsTemplate is not initialized when the test is run. But it works when the endpoint is invoked via postman

        uploadService.uploadFile(dummyInvoice);

        System.out.println("TEST 3 >>>>>>>>>>>>>>>>>> ");

    }
}

【问题讨论】:

    标签: spring mongodb spring-boot spring-data mockito


    【解决方案1】:

    问题是因为您使用@InjectMocks 来自动装配您的UploadService。 UploadService 自动装配另外两个 bean SequenceRepository 和 GridFsTemplate。

    如果您正在进行 TDD(我们可以先更改测试) – 这段代码的客户不知道额外的依赖, 因为它完全隐藏了

    Javadoc 声明:

    Mockito 将尝试仅通过构造函数注入来注入模拟, setter 注入,或按顺序和描述的属性注入 以下。如果以下任何策略失败,则 Mockito 不会 报告失败;即您必须自己提供依赖项。

    解决方案是使用 UploadServiceImpl 构造函数来自动装配 bean:

    @Service
    public final class UploadServiceImpl implements UploadService {
    
        private final SequenceRepository sequenceDao;
        private final GridFsTemplate gridFsTemplate;
        private final PlannerClient plannerClient;
    
        @Autowired
        public PlannerServiceImpl(PlannerClient plannerClient, GridFsTemplate gridFsTemplate, SequenceRepository sequenceDao) {
            this.plannerClient = plannerClient;
        }
    ...
    
    }
    

    当需要更多的依赖时,它们清晰可见,因为它们是在构造函数中初始化的

    更详细:

    https://tedvinke.wordpress.com/2014/02/13/mockito-why-you-should-not-use-injectmocks-annotation-to-autowire-fields/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-23
      • 2013-03-04
      • 2018-06-10
      • 1970-01-01
      • 2020-11-20
      • 2019-01-23
      • 2022-11-11
      • 2020-02-10
      相关资源
      最近更新 更多