我试图在此模块中找到一种模拟Redis的方法:
const Redis = require('ioredis'); const myFunction = { exists: (thingToCheck) { let redis_client = new Redis( 6379, process.env.REDIS_URL, { connectTimeout: 75, dropBufferSupport: true, retryStrategy: functionHere }); redis_client.exists(thingToCheck, function (err, resp) { // handlings in here }); } };
使用以下测试代码:
const LambdaTester = require('lambda-tester'); const chai = require('chai'); const expect = chai.expect; const sinon = require('sinon'); const mockRedis = sinon.mock(require('ioredis')); describe( 'A Redis Connection error', function() { before(() => { mockRedis.expects('constructor').returns({ exists: (sha, callback) => { callback('error!', null); } }); }); it( 'It returns a database error', function() { return LambdaTester(lambdaToTest) .event(thingToCheck) .expectError((err) => { expect(err.message).to.equal('Database error'); }); }); });
我还尝试了一些变体,但由于基本需要模拟构造函数,因此我有点受阻,我不确定Sinon是否支持这一点?
mockRedis.expects('exists').returns( (thing, callback) => { callback('error!', null); } ); sinon.stub(mockRedis, 'constructor').callsFake(() => console.log('test!')); sinon.stub(mockRedis, 'exists').callsFake(() => console.log('test!'));
不知道在这里还有什么尝试,我也尝试按照这里的建议使用rewire,但是从不设置该私有变量。mockRedis.__set__("exists",myMock);
mockRedis.__set__("exists",myMock);
我想最终伪造我的错误路径。 我很想听听其他人在测试Node js中的Redis所做的事情。
您的问题不是Sinon是否支持这一点,而是您对Ecmascript中“类”的工作方式缺少了解,如尝试在constructor测试代码中对属性进行存根显示。这将永远不会起作用,因为该属性与结果对象的结果无关。它只是对用于创建对象的函数的引用。我在Sinon跟踪器上涵盖了一个非常相似的主题,您可能有兴趣阅读以获取一些核心JS foo :-)基本上,无法对构造函数进行存根,但是您可以强迫您的代码使用另一个构造函数通过DI或链接接缝代替它。
constructor
事实上,在同一线程中有一些答案,您将看到我涵盖了一个示例,说明我本人如何设计类使用支持通过依赖注入轻松测试的Redis。您可能想将其检出,因为它或多或少直接适用于上述示例模块。
您已经尝试使用的另一种技术是使用 链接缝 (使用rewire)。Sinon主页上有一篇不错的文章。双方rewire并proxyquire会就好在这里做的工作:我觉得你刚才通过包装要求声明以模拟复杂的事情了一下。
rewire
proxyquire
即使我是Sinon维护团队的成员,我也从未使用过该mock功能,因此我无法告诉您如何使用该功能,因为我认为它使测试变得晦涩难懂,但是要使基本的链接接缝正常工作,rewire我基本上会删除所有Sinon首先编写代码,然后进行基本的案例研究(删除redis已创建的存根模块)。
mock
redis
只有这样,才能根据需要添加Sinon代码。