繁体   English   中英

Sinon - 我可以暂时模拟存根上的方法吗?

[英]Sinon - Can I temporarily mock a method on a stub?

我正在对遗留代码进行单元测试,并设置了 sinon 和 proxyquire 来为依赖项注入存根。

在某些测试中,我需要验证一个或多个依赖项上的方法是否被正确调用,同时允许对同一对象的所有其他方法调用表现得像存根(返回默认值,而不是将调用传递给真正的实现。

到目前为止,我已经尝试了多种方法,偶尔让它看起来可以工作,直到我做了一些代码清理,然后事情再次中断(当它工作时,代码的形状很差 - 所以虽然它看起来像它工作目前尚不清楚它是否会继续工作或哪些代码实际上具有预期的效果)。

以下是我目前正在尝试的内容,并对我的意图进行了评论。

const proxyquire = require('proxyquire')
const stubUtils = stub(require('./utils'))
const stubService = stub(require('./service'))

// Setup the SuT to default to talking to stubs
const systemUnderTest = proxyquire('./index', {
    './utils': stubUtils,
    './service': stubService
})

let sandbox
describe('index.doSomething()', () => {
    beforeEach(() => {
        // I'm attempting to revert any test-specific setup and put the dependencies back to default stubs
        sinon.reset();

        // the legacy code is configured by environment variables, between tests I want to reset process.env since each test requires a different configuration
        sandbox = sinon.createSandbox()
        sandbox.stub(process, 'env').value({})

        // someMethod() is printed in a bunch of logs which call .length on it, so my baseline setup needs to configure it
        stubService.someMethod.returns('')
    })

    afterEach(() => {
        // tests *should* call their own .verify(), but I'm assuming adding it here will catch it if the tests miss it
        sinon.verify()
        sandbox.restore()
    })

    // There are several basic "modes" for the code under test
    describe('Scenario A', () => {
        beforeEach('Scenario A Setup', () => {
            // Each scenario sets a few common settings
            process.env.SOME_CONFIG_VALUE = 'mode A'
            // ...
        })

        it('uses the environment variable appropriately', () => {
            // Here's where I'm struggling
            // In this one test I need to verify a call is made with the correct argument on an object that is otherwise behaving like a stub
            const expected = "the expected value"
            process.env.IMPORTANT_VALUE = expected

            // throws: stubUtils.restore is not a function
            //stubUtils.restore()

            // throws: TypeError: Attempted to wrap someMethod which is already wrapped
            const mockCall = sinon.mock(stubUtils).expects('someMethod').withArgs(expected)

            systemUnderTest.doSomething()

            mockCall.verify()
        })

        // it(...  // more tests, similarly needing to mock various methods on the stubs
    })

    // describe('Scenario B', () => {
    // ... and so on.  There are several scenarios, each with several unit tests

我想到了。 我遇到的问题的根源是我正在stub() 'ing 整个 object 并期望能够.restore()它。

但是, .restore()方法仍然存在于对象的方法中,而不是 object 本身。

这是我的错误的一个例子:

const myObj = { doSomething: () => {} }
const stubObj = sinon.stub(myObj)
stubObj.restore()

在这里通过将.restore()调用移动到function来修复它:

const myObj = { doSomething: () => {} }
const stubObj = sinon.stub(myObj)
stubObj.doSomething.restore()

附言...

我还发现我通过使用存根得到了最好的测试 output。 以前我认为我需要使用mock().expects后跟.verify() 这行得通,它包括哪些参数不匹配的详细信息。

但是,我发现sinon.assert.calledWithMatch(stubObj.doSomething, expected)的 output 是最容易阅读并准确找出失败原因的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM