当前位置: 首页 > 知识库问答 >
问题:

Sinon间谍未触发

尉迟俊能
2023-03-14

我很难找到sinon间谍没有被触发的原因。在下面的测试中,两个控制台语句都报告为false,因此两个方法都没有被调用(以防出现错误)。

这是我的一个摩卡测试通常的样子:

describe('Post Controller', function () {
    var controller = require('../controllers/PostController'),
    req = {
        user: {
            check_id: "00100",
            access_id: "54876329"
        }
    };

beforeEach(function () {
    res = {
        send: sinon.spy(),
        json: sinon.spy()
    };
});

afterEach(function () {
    res.send.reset();

});

describe('readAllPosts', function () {
    it('should return an array of posts', function (done) {
        controller.readAllPosts(req, res);
        process.nextTick(function () {
            console.log('send: ', res.send.called);
            console.log('json: ', res.json.called);
            assert(res.json.calledWith(sinon.match.array));
            done();
        });
    });
});

});

PostOnToller中的readAllPosts方法:

var postController = {
    readAllPosts: function (req, res) {
        PostModel.find(
            {
                access_id: req.user.access_id
            },
            function (err, results) {
                if (err) {
                    res.send(404, err);
                } else {
                    // res here is a spy
                    res.json(results);
                }
            }
        );
    }
};

最后是PostModel中的find方法

Posts.find= function (conditions, cb) {
    /* ... */
    dbQuery(query, function (err, results) {
        if (err) {
            cb(err);
        }

        cb(null, results);
    });
};

如果我以正常的方式调用方法,它们会执行查找,返回预期的Posts数组。但是,不会执行res间谍。另外,如果我将控制器类中的方法更改为

var postController = {
    readAllPosts: function (req, res) {
        res.json([{this:"that",and:"other"}]);
    }
};

间谍函数(res)确实会开火。我知道发送到Model的回调正在被调用,res对象在那里,但它没有被调用。我不认为这是一个间接的问题(调用原始方法而不是sinon包装的方法),但我不确定问题在哪里。

共有1个答案

易风华
2023-03-14

使用Sinon spies/stubs测试异步函数是很困难的,因为(AFAIK)您无法让它在被调用时告诉您(它甚至可能永远不会被调用)。

在您的例子中,您假设PostModel。find()将在下一个勾号中完成(根据您使用的process.nextTick()),很可能不是这样,因此您正在检查您的间谍,而此时查询仍在运行,并且还没有调用任何间谍。

在我看来,您试图用一个测试来测试太多内容:PostModel。find()dbQuery()控制器。readAllPosts()。我可能会在不同的测试中将它们分开,并将其余部分存根。

例如,如果你想检查你的控制器是否发送回正确的响应,或者它是否正确地处理错误,存根PostModel.find()让它(同步地)调用回调,要么有错误,要么有正确的结果数组,并随后检查res.send/res.json间谍。

另一个选择是不使用间谍,而是简单的回调。例如:

controller.readAllPosts(req, {
  send : function(data) {
    assert(data, ...);
    done();
  },
  json : function(data) {
    assert(data, ...);
    done();
  },
});

(或其变更)

然而,我不喜欢这样做,因为它会阻止您测试(以一种简单的方式)这些方法并没有被调用。

 类似资料:
  • 我试图理解西农图书馆的假、间谍、存根和模拟之间的区别,但无法清楚地理解。 有人能帮我了解一下吗?

  • 问题内容: 我有内部类的课程,如下所示: 模仿测试如下所示:build.gradle: 测试: 第一次测试正在按预期方式工作。第二个永远不会被检测为“已调用”,尽管在日志中我看到的是。有什么问题吗?:) 谢谢! 问题答案: 怎么了? 好吧,这里的问题非常微妙,当您调用时,会在实例背后创建某种装饰器,以允许监视实例上的所有方法调用。因此,您可以检查给定方法被调用了多少次, 但是在装饰器 上 却 没有

  • 所以我有一个调用https请求的方法。我已经成功地在其他测试中中断了调用,但是这个测试打败了我,因为它根本不起作用。 在我的beforeach中,我创建存根,在我的afterEach中,我执行存根还原 在测试中,我创建了四个存根调用。

  • Mockito——我知道间谍在对象上调用实际方法,而模拟在双对象上调用方法。此外,除非有代码气味,否则要避免间谍。然而,间谍是如何工作的?我应该在什么时候使用他们?它们与模拟有什么不同?

  • 问题内容: 我有两个Redis客户端,在一个文件中,我有一个简单的脚本设置并删除了Redis密钥: 在第二个文件中,我有一个Redis客户端充当订户: 关键的“占位符”已设置,那么是否有充分的理由使我在“消息”处理程序中未获得任何输出? 问题答案: 您忘记了订阅用户客户端订阅特定的频道。此外,如果要监视所有事件,则需要使用基于模式的订阅。 您可能想要执行以下操作(未测试): 请参阅Redis文档和

  • 我在两个无界流之间有一个简单的间隔连接。这适用于较小的工作负载,但对于较大的(正式生产环境),它不再有效。通过观察输出,我可以看到FlinkSQL作业仅在扫描整个主题(并因此读入内存?)后才触发/发出记录,但我希望作业在找到ingle匹配后立即触发记录。因为在我的正式生产环境中,作业无法承受将整个表读入内存。 我正在做的间隔连接与这里提供的示例非常相似:https://github.com/ver