2016-06-24 2 views
2

Ich entwickle eine Spring Boot App. Die Service-Methode lädt ein PDF-Dokument mit Hilfe von GridFsTemplate, das im Service automatisch gesendet wird, in einen Mongoob Repo. Diese Datei-Upload-Service-Methode funktioniert wie erwartet über den Postman Rest Client. Aber, als ich versuchte, einen Komponententest zu laufen; Die SpringData GridFsTemplate wird nicht aufgerufen (in MongoDB können Sie GridFS zum Speichern von Binärdateien verwenden). Dies führt dazu, dass org.springframework.data.mongodb.gridfs.GridFsTemplate.store (...) eine NullPointerException auslöst. Bitte, kannst du mir helfen, ich bin seit ein paar Tagen darin stecken geblieben.GridFsTemplate NullPointerException in der Service Unit Test Klasse (Tech Stack: Spring Data/Spring Boot/Micro Service/Mongodb)

Unten ist mein Service-Implementierung:

@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; 
     } 
    } 
### Unten ist mein Unit-Test-Klasse für den Dienst
@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 >>>>>>>>>>>>>>>>>> "); 

    } 
} 

Antwort

1

Das Problem ist, weil Sie @InjectMocks verwenden Ihre UploadService autowire. Und UploadService autowire zwei weitere Beans SequenceRepository und GridFsTemplate.

Wenn Sie tun TDD oder nicht (und wir sind in der Lage den Test zuerst ändern) - weiß nicht, über eine zusätzliche Abhängigkeit, Klienten dieser Code, weil es völlig

versteckt

Die Javadoc Staaten:

Mockito werden versuchen, Mocks zu injizieren nur entweder durch Konstruktor Injektion, Setter Injektion oder Eigenschaft Injektion in Ordnung und als beschrieben unten. Wenn eine der folgenden Strategien fehlschlägt, gibt Mockito keinen Fehler aus . Das heißt, Sie müssen selbst Abhängigkeiten bereitstellen.

Die Lösung ist UploadServiceImpl Konstruktor zu verwenden Bohnen autowire:

@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; 
    } 
... 

} 

Wenn es mehr Abhängigkeiten benötigt, sie sind klar in Sicht, weil sie im Konstruktor

Detailliertere initialisiert werden:

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

Verwandte Themen