【问题标题】:Unit Test: Stub/rewire a function inside a server request单元测试:存根/重新连接服务器请求中的函数
【发布时间】:2020-01-25 23:43:55
【问题描述】:

我想测试一个进行外部 api 调用的路由。 我想存根functionThatShouldBeStubbed,这样我就可以跳过外部api调用,而是专注于测试路由。

我正在使用 Sinon 并重新连线,因为如果我理解正确,我无法存根以当前方式导出的函数。

但是,似乎即使 rewire 替换了该功能,我的测试仍在进行外部 api 调用。似乎 sinon 不知道该功能已重新布线。我怎样才能使这种情况有效?



//--------------------------
//../target.js
const functionThatShouldBeStubbed = async () => {
    const results = await external_API_call();
    return results;
}

module.exports = { 
 functionThatShouldBeStubbed, 
 /*more other functions*/
}

//--------------------------
//../index.js
app.use(require('endpoint.js'));

//--------------------------
//endpoint.js
const { functionThatShouldBeStubbed } = require("target.js");
router.post('endpoint', async(req, res) => {
    //do lots of stuff

    const results = await functionThatShouldBeStubbed();
    if(results.error) { return res.status(207).send({ /*stuff */})}
    //...more stuff
})


//--------------------------
//test.js
const server = require("../index.js");
const rewire = require('rewire')
const restoreTarget = rewire('../target.js');


describe("Should return appropriate error code to requester", function () {
    it("Should return 207 in this case", function (done) {
        const targetStub = sinon.stub().resolves({msg: 'fake results', statusCode: 207})
        const targetRewired = restoreTarget.__set__("functionThatShouldBeStubbed", targetStub);

        chai.request(server)
            .post("/endpoint")
            .send('stuff over')
            .catch((error) => {
                console.log("Error: ", error)
                done();
            })
            .then((res) => {
                expect(targetStub.callCount).to.equal(1);
                res.should.have.status(207);

                restoreTarget();
                targetStub.restore();
                done();
            })
    })
})

非常感谢! 编辑:更新代码以获取更多详细信息 Edit2:再次更新代码以显示导入方法

【问题讨论】:

    标签: javascript node.js unit-testing chai sinon


    【解决方案1】:

    根据您的模块的导出方式,您根本不需要rewire。以下应该工作

    //test.js
    const target = require ("../target");
    const server = require("../index");
    
    describe("Should return appropriate error code to requester", () => {
      it("Should return 207 in this case", done => {
        const targetStub = sinon
          .stub(target, "functionThatShouldBeStubbed")
          .resolves({msg: 'fake results', statusCode: 207})
        chai.request(server)
          .post("/endpoint")
          .send('stuff over')
          .then(res => {
             expect(targetStub.callCount).to.equal(1);
             res.should.have.status(207);
             targetStub.restore();
             done();
          })
      })
    })
    

    【讨论】:

    • 我试过你的代码,但它仍在调用外部 api。我可以看到创建了一个存根,但是当代码执行时它仍然调用原始函数而不是存根。似乎我存根的功能与在路由器中执行的功能不同。你有什么建议我可以研究一下吗?谢谢你。编辑:我更新了原始代码,希望能提供更多信息。再次非常感谢您。
    • @fishcakesAndCoffee 你在导入时碰巧解构了函数吗?即const { func } = ...,如果是这样,您需要导入整个模块,然后取出要使用的单个函数。
    • 模块是完整导入的const target = require('../target.js'),所以我不认为这是部分。另一件事是我对第三方模块存根没有问题(如果这是正确的术语),即我通过 npm 安装的包。我已经能够存根诸如 ```request-promisify` 的 POST 调用之类的东西。主要是我自己编写的函数,我无法存根。
    • @fishcakesAndCoffee 但它是否在您的代码和测试中完整导入?您的示例代码表明它不是?我以前在这个话题上answered a question,虽然情况不同,但可能会出现同样的问题。不过,正如我所说,只有在摇树且不包括完整导出的对象时,这才会成为问题。
    • 我真的很抱歉让你一次又一次地重新审视这个问题,但我真的很迷茫我做错了什么。 target.js 导出一个解构对象,例如 ``` modules.export = { func1, func2, func3...}. That file is then imported into the test file, as const target = require('../target.js')```我的理解是完全导入它。我在这里有什么误解吗?非常感谢您花时间回答所有问题。
    猜你喜欢
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    • 2011-08-09
    • 2018-11-20
    相关资源
    最近更新 更多