服务单元测试类中的GridFsTemplate NullPointerException(技术堆栈:Spring数据/ Spring Boot / Micro服务/ Mongodb)

时间:2016-06-24 13:32:27

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

我正在开发一个春季启动应用程序。 服务方法使用在服务中自动装配的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 >>>>>>>>>>>>>>>>>> ");

    }
}

1 个答案:

答案 0 :(得分:1)

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

  

如果您正在进行TDD(我们可以先更改测试)    - 此代码的客户端不知道其他依赖项,   因为它完全隐藏了

Javadoc声明:

  

Mockito将尝试仅通过构造函数注入注入模拟,   按照顺序和所描述的方式进行注入或注入   下面。如果以下任何一种策略失败,那么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;
    }
...

}

当需要更多依赖项时,它们很明显,因为它们是在构造函数

中初始化的

更详细:

general contract