无法使用 Mockito 模拟 MongoTemplate executeQuery

Unable to mock MongoTemplate executeQuery using Mockito

我正在寻找模拟 MongoTemplate,以便实际调用我服务中的 executeQuery 函数。 这是我的服务代码块的样子:

 this.mongoTemplate.executeQuery(query, collectionName, new DocumentCallbackHandler() {

            @Override
            public void processDocument(Document document) throws MongoException, DataAccessException {
                try {
                    // convert to strongly typed object
                  System.out.println("Actual method called");
                    ProductDayData pdd = mongoTemplate.getConverter().read(ProductDayData.class, document);

                    // call copyover
                    backFillOneEvent(pdd, liveContractIds, pddType, toDate, now, timeAtStartOfDay);
                } catch (RuntimeException e) {
                    LOGGER.error("FATAL: backfill - error processing document: {}", document, e);
                } catch (Throwable t) {
                    LOGGER.error("FATAL: backfill - error processing document: {}", document, t);
                    throw t;
                }
            }

        });

在我的单元测试中,这是我所做的:

@Mock
  private MongoTemplate mongoTemplate;

service = new MyService(mongoTemplate); //mock is set
Mockito.doCallRealMethod().when(mongoTemplate).executeQuery(Mockito.any(Query.class),Mockito.any(String.class),Mockito.any(DocumentCallbackHandler.class));

doCallRealMethod() 显然没有做任何事情,我希望它触发实际方法。

您需要使用 Spy 而不是 Mock

MongoTemplate mongoTemplate = Mockito.spy(
    //Instance the MongoTemplate, use any test framework
    new MongoTemplate(new SimpleMongoClientDbFactory("mongodb://localhost/test"))
);
// Since it's spy, by default, it will execute real method
//Skipping stub Mockito.doCallRealMethod()....

System.out.println("Real");
mongoTemplate.executeQuery(query, collectionName, new DocumentCallbackHandler() {

        @Override
        public void processDocument(Document document) throws MongoException, DataAccessException {
            //Simplified version
            System.out.println("Actual method called:" + document.toJson());
        }

    });
System.out.println("End Real");

//Now call fake `executeQuery`
Mockito.doNothing().when(mongoTemplate).executeQuery(Mockito.any(Query.class), Mockito.any(String.class),
            Mockito.any(DocumentCallbackHandler.class));
System.out.println("Mock");
mongoTemplate.executeQuery(query, collectionName, new DocumentCallbackHandler() {

        @Override
        public void processDocument(Document document) throws MongoException, DataAccessException {
            //Simplified version
            System.out.println("Actual method called:" + document.toJson());
        }

});
System.out.println("End Mock");

//Now we "enable" real method call  
Mockito.doCallRealMethod().when(mongoTemplate).executeQuery(Mockito.any(Query.class), Mockito.any(String.class),
        Mockito.any(DocumentCallbackHandler.class));
System.out.println("Real 2");
mongoTemplate.executeQuery(query, collectionName, new DocumentCallbackHandler() {

    @Override
    public void processDocument(Document document) throws MongoException, DataAccessException {
        System.out.println("Actual method called:" + document.toJson());
    }

});
System.out.println("End Real 2");

--输出---

Real
//MongoDB traces...
Actual method called:{...}
Actual method called:{...}
...
End Real
Mock
End Mock
Real 2
//MongoDB traces...
Actual method called:{...}
Actual method called:{...}
...
End Real 2

链接:@Mock vs @Spy