用 Sinon.js 模拟要注入的依赖项

Mocking out with Sinon.js a dependency to be injected

具有以下 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();
});});

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

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

sinon.spy(BalanceRepository) 并不意味着 class 方法会被自动侦测(它们不会)。

TransactionService 期望 BalanceRepository 实例,而 fakeBalanceRepo 是构造函数。

如果目的是监视 class 方法而不改变其行为,则它是:

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

正如 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();
});