【问题标题】:Original function is called instead of stub调用原始函数而不是存根
【发布时间】:2013-08-03 01:57:39
【问题描述】:

我在让诗乃的存根正常工作时遇到问题。当我在retro 上存根list 并运行测试时,app.get('/retro', retro.list) 正在执行原始函数retro.list 而不是存根。由于发生这种情况,测试失败,因为存根的callCount 为 0。

我对coffeescript 更熟悉,而且我也以同样的方式存根。关于 Javascript 的作用域,或者require('../routes/retro') 的工作原理,或者retroapp.jstest.js 中的不同,我是否有什么不明白的地方。

非常感谢下面的帮助和代码。

test.js:

var request = require('supertest')
  , retro = require('../routes/retro')
  , app = require('../app')
  , sinon = require('sinon');
require('should'); 

describe('GET /retro', function() {
  // less involved, but maybe stupid to test
  it('should call retro.list', function(done) {
    var stub = sinon.stub(retro, 'list');

    request(app)
      .get('/retro')
      .end(function(err, res){
        stub.callCount.should.equal(1);

        if (err) return done(err);
        done();
      })
  })
})

app.js:

var express = require('express')
  , config = require('./config')
  , routes = require('./routes')
  , retro = require('./routes/retro');

var app = express();
config(app);

app.get('/', routes.index);
app.get('/retro', retro.list);

module.exports = app;

retro.js:

var retro = {
  list: function(req, res){
    console.log('actual called');
    res.send("respond with a resource");
  }
}

module.exports = retro;

【问题讨论】:

  • retro 返回什么?它是普通对象还是新创建的实例?
  • 试试这个retro.list.callCount.should.equal(1);
  • @mor 我包含了retro.js,所以你可以看到它返回的对象。它不是一个实例。我正在考虑导出一个实例并尝试对原型进行存根,但这也不是很好。
  • @Sushanth-- 我尝试了您的建议,但 sinon.stub(retro, 'list')retro.list 返回存根,因此它们是同一个对象,运行该代码会产生相同的问题。不过感谢您的建议

标签: javascript express mocha.js stub sinon


【解决方案1】:

在要求/创建 app 之前,您可能需要创建存根。

var request = require('supertest')
  , sinon = require('sinon')
  , retro = require('../routes/retro');

var stubRetroList = sinon.stub(retro, 'list');

var app = require('../app');

// ...

    stubRetroList.callCount.should.equal(1);

这允许retro.list 在传递到路由之前更新:

app.get('/retro', retro.list);

问题可能是因为retro.list 不是按引用(指针)传递的,而是按值传递(复制)的引用。因此,虽然sinon.stub() 正在改变retro.list,但它不会影响'/retro' 路由已经拥有的副本。

【讨论】:

  • 谢谢乔纳森!这非常有效。不确定我是否喜欢在上面存根,但我很高兴我明白它是在存根引用/副本而不是同一个对象。
  • proxyquire 是一个更好的解决方案
【解决方案2】:

我遇到了同样的问题,接受的答案(虽然是真的)没有帮助。事实证明,为了让sinon 存根工作,存根方法不能在同一个模块中使用。换句话说,存根模块端点只会存根模块端点,而不是module.exports引用的函数的内部使用。

举例说明:

模块.js

const express = require('express')
const router = express.Router()

router.get('/', function (req, res) {
  res.status(200).json(list())
})

function list() {
    return ['something']
}

module.exports = {
    router: router,
    list: list
}

module.spec.js

// This stub will not work
sinon.stub(module, 'list').callsFake(() => ['something else'])

要使其正常工作,您必须将要存根的内容分离到其自己的模块中并以这种方式使用它:

sub_module.js

function list() {
    return ['something']
}

module.exports = {
    list: list
}

现在sub_module.list() 可以被存根了。

(OP 定义了一个方法,所以这对他来说不是问题)

【讨论】:

    猜你喜欢
    • 2017-01-16
    • 2016-08-19
    • 2018-03-05
    • 1970-01-01
    • 2021-11-03
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    • 2023-03-15
    相关资源
    最近更新 更多