【问题标题】:Mocking out with Sinon.js a dependency to be injected使用 Sinon.js 模拟要注入的依赖项
【发布时间】:2018-09-20 14:01:49
【问题描述】:

具有以下 balanceRepository.js 文件。

module.exports = function(){
this.getBalance = (accountId)=>{
    throw 'NotImplementedException';
};};

还有服务transactionService.js文件。

module.exports = function(balanceRepo){
this.isTransactionAllowed = (amount, accountId)=>{
    const balance = balanceRepo.getBalance(accountId);
    return amount <= balance;
};};

我想进行单元测试,当我们调用 transactionService.isTransactionAllowed 时,它会在内部调用 balanceRepository.getBalance。我期待下面的代码能够工作。

let BalanceRepository = require('../balanceRepository');
let TransactionService = require('../transactionService');

let should = require('should');
let sinon = require('sinon');

describe('transaction service', ()=>{
   let fakeBalanceRepo = sinon.spy(BalanceRepository);
   let transactionSrv = new TransactionService(fakeBalanceRepo);

   transactionSrv.isTransactionAllowed(100, 987654321);

   it('should call getBalance', ()=>{
      fakeBalanceRepo.getBalance.should.be.called();
});});

我创建了 BalanceRepository 类的间谍。我将该间谍对象注入到我的 TransactionService 的实际实现中。然后,我断言在 spy 上调用了 getBalance 方法。这对我来说很有意义,但它不起作用!

我怎样才能注入一个假的并断言它的一个方法被调用了?

【问题讨论】:

    标签: node.js unit-testing mocha.js sinon should.js


    【解决方案1】:

    sinon.spy(BalanceRepository) 并不意味着类方法会被自动监视(它们不会)。

    TransactionService 需要 BalanceRepository 实例,而 fakeBalanceRepo 是构造函数。

    如果目的是监视类方法而不是改变其行为,那么它是:

       let balanceRepo = new BalanceRepository;
       sinon.spy(balanceRepo, 'isTransactionAllowed')
       let transactionSrv = new TransactionService(balanceRepo);
       transactionSrv.isTransactionAllowed(100, 987654321);
       balanceRepo.getBalance.should.be.called();
    

    【讨论】:

    • 我确实尝试过,但它也不起作用。如果我们向 TransactionService 注入 BalanceRepository 的真正实现,它将调用真正的 getBalance 并抛出“NotImplementedException”。在实际场景中会尝试连接到数据库。很明显,我们不希望在单元测试中这样做。我错过了什么吗?
    • 不清楚原始代码有什么问题。是的,在单元测试中需要存根 DB 调用。如果您需要模拟实现,请使用sinon.stub,而不是sinon.spy
    【解决方案2】:

    这正如 estus 所评论的那样有效。

    let balanceRepo = new BalanceRepository();
    let fakeGetBalance = sinon.stub(balanceRepo, 'getBalance');
    
    let transactionSrv = new TransactionService(balanceRepo);
    transactionSrv.isTransactionAllowed(100, 987654321);
    
    it('should call getBalance', ()=>{
        fakeGetBalance.should.be.called();
    });
    

    【讨论】:

      猜你喜欢
      • 2020-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多