如何在Mongo(ose)/ Express应用程序中测试承诺?

时间:2014-04-02 20:30:17

标签: express mongoose promise mocha

我使用promises在(expressJS)路由的末尾包装异步(Mongo)DB操作。 我想尝试弄清楚如何测试以下代码。

userService

userService.findOne = function (id) {

    var deferred = q.defer();

    User.findOne({"_id" : id})
        .exec(function (error, user) {
            if (error) {
                deferred.reject(error);
            } else {
                deferred.resolve(user);
            }
        });

    return deferred.promise;
};

userRoute

var user = function (req, res) {
    var userId = req.params.id
         , userService = req.load("userService");
         // custom middleware that enables me to inject mocks

    return userService.findOne(id)
        .then(function (user) {
            console.log("called then");
            res.json({
                msg: "foo"
            });
        }).catch(function (error) {
            console.log("called catch");
            res.json({
                error: error
            });
        }).done();
};

这是尝试使用mocha

测试上述内容

userTest

it("when resolved", function (done) {

    var jsonSpy = sinon.spy(httpMock.res, "json")
        , httpMock = require("/path/to/mock/http/object")
        , serviceMock = require("/path/to/mock/service"),
        , deferred = q.defer()
        , findStub = sinon.stub(serviceMock, "findOne")
            .returns(deferred.promise)
        , loadStub = sinon.stub(httpMock.req, "load")
            .returns(serviceMock),
        retPromise;


    // trigger route
    routes.user(httpMock.req, httpMock.res);

    // force promise to resolve?
    deferred.resolve(); 

    expect(jsonSpy.called).to.be.true; // fails

    // chai as promised 
    retPromise = findStub.returnValues[0];
    expect(retPromise).to.be.fulfilled; // passes
});

http mock只是一个没有操作的空对象,expressJS通常会开始渲染东西。我在这些无操作中添加了一些日志记录,以便了解它是如何挂在一起的。

这并不是很有效。我想验证整体是如何整合的,以建立某种回归套件 - 但我已经有效地嘲笑了它,并且我只是测试我的模拟(不完全成功)。

我还注意到控制台登录我的http模拟内部由then和catch触发了两次 - 但是在实际代码中调用的jsonSpy(通过在userRoute代码中注销sinon间谍来验证)没有在测试中调用。

有没有人对Mongo支持的快递应用程序的集成测试策略有所建议?

1 个答案:

答案 0 :(得分:0)

在你检查结果是否被调用之前,我认为你并没有给你的承诺一个机会。在设置jsonSpy.called之前,您需要异步等待userService.findOne()的promise链完成。试试这个:

    // start of code as normal

    q.when(
        routes.user(httpMock.req, httpMock.res),
        function() { expect(jsonSpy.called).to.be.true; }
    );

    deferred.resolve();

    // rest of code as normal

那应该链接routes.user()promise并按预期传递。

提醒一句:我不熟悉您的框架,所以我不知道它是否会耐心地等待所有异步事件发生。如果它给你回调你的延迟链时遇到问题,你可能想尝试使用nodeunit,它可以很好地处理异步测试(IMO)。