0

我想编写一个测试来更新博客文章(或其他): * 在数据库中插入博客文章 * 获取博客文章在 MongoDb 中获得的 ID * 将更新版本发布到我的端点 * 请求完成后:检查在已完成更新的数据库中

这是这个,使用koa

var db = require('../lib/db.js');
describe('a test suite', function(){
    it('updates an existing text', function (done) {
      co(function * () {
        var insertedPost = yield db.postCollection.insert({ title : "Title", content : "My awesome content"});
        var id =  insertedPost._id;
        var url = "/post/" + id;
        var updatedPost = { content : 'Awesomer content' };

        request
            .post(url)
            .send(updatedTextData)
            .expect(302)
            .expect('location', url)
            .end(function () {
                co(function *() {
                    var p = yield db.postCollection.findById(id);
                    p.content.should.equal(updatedPost.content);
                    console.log("CHECKED DB");
                })(done());
            });
        });
    });
});

我意识到那里有很多活动部件,但我已经分别测试了所有交互。这是我包含的 db 文件(我知道它工作正常,因为我在生产中使用它):

var monk = require('monk');
var wrap = require('co-monk');

function getCollection(mongoUrl, collectionName) {
    var db = monk(mongoUrl);
    return wrap(db.get(collectionName));
};

module.exports.postCollection   = getCollection([SECRET MONGO CONNECTION], 'posts');

生产代码按预期工作。这个测试通过了,但在我看来,就像 .end() 子句中的协同函数永远不会运行......但是 done() 调用被调用了。至少没有打印“CHECKED DB”。

我试过用“done()”和“done”没有。有时这有效,有时无效。我试图将数据库检查移到请求之外......但这只是挂起,因为 supertest 希望我们在完成时调用 done()。

所有这一切让我感到困惑和害怕(:)) - 我在这里做错了什么。

4

2 回答 2

3

意识到这个问题非常冗长和具体,我担心我永远不会得到正确的答案。由于问得不好。

但是给出的答案和评论让我再看一遍,我找到了。我写了一篇关于它的长博客文章,但我会在这里给出它的结尾作为总结。如果它没有意义,那么博客文章中还有更多相同的内容:)。

这是 TL;DR:

我想在发出请求后检查数据库的状态。这可以使用supertest的 .end() 函数来完成。

因为我使用了co-monk,所以我希望能够使用 yield 和 generators 来做到这一点。这意味着我需要用co包装我的生成器函数。

co,从 4.0.0 版开始,返回一个承诺。这对于mocha的用户来说是完美的,因为它允许我们使用 .then() 函数并将 done 变量传递给 .then(fn success, fn failure(err)) 的成功和失败函数。

整个测试如下所示。由于断言失败,运行它会返回错误,正如我想要的那样:

var co = require("co");
var should = require("should");
var helpers = require('./testHelpers.js');
var users = helpers.users;
var request = helpers.request;

describe('POST to /user', function(){

    var test_user = {};

    beforeEach(function (done) {
        test_user = helpers.test_user;
        helpers.removeAll(done);
    });

    afterEach(function (done) {
        helpers.removeAll(done);
    });

    it('creates a new user for complete posted data', function(done){
        // Post
        request
            .post('/user')
            .send(test_user)
            .expect('location', /^\/user\/[0-9a-fA-F]{24}$/) // Mongo Object Id /user/234234523562512512
            .expect(201)
            .end(function () {
                co(function *() {
                    var userFromDb = yield users.findOne({ name : test_user.name });
                    userFromDb.name.should.equal("This is not the name you are looking for");
                }).then(done, done);
            });             
    });
});
于 2015-05-06T02:19:11.907 回答
1

发生这种情况是因为

 var p = yield db.postCollection.findById(id);

最后一行将在您的生成器函数中执行。

你可以通过添加一个console.log('before first yield')来测试我是否正确。

yield 是生成器函数中 return 的替代品,但如果您第二次调用该函数,它会运行到下一个 yield。

生成器函数从 yield 到 yield

(最好的方式来解释它的简短方式 - 我认为)。

您的解决方案:在数据库找到之前简单地擦除产量:

var p = db.postCollection.findById(id);
于 2015-04-19T06:42:21.620 回答