2017-08-02 66 views
0

我正在处理混合节点样式回调和蓝鸟许诺的代码,我需要为它编写一些单元测试。在诺言链末端测试回调调用

特别是,cache.js公开了init()函数,该函数使用promise。然后在另一个文件(例如index.js)中由doSomething()函数调用,该函数又接受必须在init()结尾处调用的回调。

伪代码如下:

// [ cache.js ] 
function init() { 
    return performInitialisation() 
    .then((result) => return result); 
} 


// [ index.js ] 
var cache = require('./cache'); 

function doSomething(callback) { 
    console.log('Enter'); 

    cache.init() 
    .then(() => { 
     console.log('Invoking callback'); 
     callback(null); 
    }) 
    .catch((err) => { 
     console.log('Invoking callback with error'); 
     callback(err); 
    }); 

    console.log('Exit'); 
} 

一个可能的单元测试可以(仅示出相关的代码):

// [ index.test.js ] 
... 
var mockCache = sinon.mock(cache); 
... 
it('calls the callback on success', function(done) { 
    mockCache.expects('init') 
    .resolves({}); 

    var callback = sinon.spy(); 

    doSomething(callback); 
    expect(callback).to.have.been.calledOnce; 
    done(); 
}); 

该测试通过,但是改变的期望,not.have.been.calledOnce也通过,这是错的。

此外,控制台日志顺序的:

Enter 
Exit 
Invoking callback 

我也考虑过多种可能性,其中没有一个工作:

  • 使用柴作为许诺的,例如expect(callback).to.eventually.have.been.calledOnce;

  • 重构doSomething()是简单地:

    功能的doSomething(回调){ cache.init() .asCallback(回调); }

谁能帮助我理解我在做什么错了,我怎么能解决这个问题吗?

回答

0

控制台日志顺序的

日志是正确的顺序,因为你Promise将是异步的含义,在最起码,内部控制台日志调用then & catch将运行下一个勾号。

至于为什么测试失败是几个问题的结果,第一个是你似乎没有sinon-chai配置正确,或充其量你calledOnce断言是不踢英寸只是为了确认,您的测试文件的顶部应该是这样的:

const chai = require("chai"); 
const sinonChai = require("sinon-chai"); 

chai.use(sinonChai); 

如果你有一个和它仍然无法正常工作,然后可能是值得的sinon-chai LIB打开的问题,但是,一个简单的解决方法是切换到sinon assertions如其次,当你最终确定这一点时,你可能会发现测试现在会失败......每次。原因就是你在测试中遇到了同样的问题,你在测试中遇到了同样的问题 - 在内部承诺有机会解决之前,你就断言了。解决这个的最简单方法是实际使用您的done处理器从摩卡作为您的断言

mockCache.expects('init').resolves({}); 
doSomething(() => done()); 

换句话说,如果done获取的叫那么你知道回调被称为:)

+0

谢谢你的回复。 如果我做'doSomething(()=> done());'那么我将无法测试错误条件,对吧?我的意思是我不会看到回调是否与错误参数一起被调用。 – rippeltippel

+0

@rippeltippel你处理回调,所以'done'被调用,测试通过_is_你的支票。如果由于某种原因'callback'没有被调用,你的测试会超时。 – James

+0

有道理,谢谢。 – rippeltippel

0

James“评论我重新审视我的这样的测试:

it('calls the callback on success', function(done) { 
    mockCache.expects('init') 
    .resolves({}); 

    doSomething(done); 
}); 

it('calls the callback on error', function(done) { 
    mockCache.expects('init') 
    .rejects('Error'); 

    doSomething((err) => { 
    if (err === 'Error') { 
     done(); 
    } else { 
     done(err); 
    } 
    }); 
});