Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/422.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
函数中创建的JavaScript对象的模拟方法_Javascript_Mocking_Chai_Sinon_Stub - Fatal编程技术网

函数中创建的JavaScript对象的模拟方法

函数中创建的JavaScript对象的模拟方法,javascript,mocking,chai,sinon,stub,Javascript,Mocking,Chai,Sinon,Stub,我编写了一个JavaScript函数,它从require()d库创建一个对象,然后使用它。当我试图为它编写测试时,这似乎给我带来了麻烦,因为我似乎没有一个好的方法来控制该对象并创建其方法的模拟来测试我的函数的行为 我遇到这种情况是因为我设计的函数很差吗?我来自Java/Spring的背景,所以我脑子里的声音都在尖叫“依赖注入”。有没有比仅仅将函数所需的对象作为参数传递给它更好的方法呢 示例函数: //dbService.js const AWS=require('AWS-sdk'); 函数get

我编写了一个JavaScript函数,它从require()d库创建一个对象,然后使用它。当我试图为它编写测试时,这似乎给我带来了麻烦,因为我似乎没有一个好的方法来控制该对象并创建其方法的模拟来测试我的函数的行为

我遇到这种情况是因为我设计的函数很差吗?我来自Java/Spring的背景,所以我脑子里的声音都在尖叫“依赖注入”。有没有比仅仅将函数所需的对象作为参数传递给它更好的方法呢

示例函数:

//dbService.js
const AWS=require('AWS-sdk');
函数getItem(){
const dynamo=new AWS.DynamoDB.DocumentClient();
var params={/*无关*/}
试一试{
return wait dynamo.get(getParams.promise();
}捕捉(错误){
返回错误;
}
}
exports.getItem=getItem;
dynamo.get()
成功返回或抛出错误时,当我试图编写测试来验证函数的行为时,我开始遇到阻塞

示例测试(我使用Sinon进行模拟,使用Chai进行断言):

//dbserviceest.js
const sinon=要求(“sinon”);
const dbService=require('dbService.js');
const expect=require('chai')。expect;
description('dbService:When database return a record',function(){
设dbMock,dbServiceResp=null;
beforeach(异步函数(){
dbMock=sinon.stub(dynamo,“get”)
.returns({Item:'an Item});
dbServiceResp=等待dbService.getItem(“一项”);
});
之后(函数(){
restore();
});
它('应该有期望值',函数(){
expect(dbservicesp.Item).to.be.equal(“一项”);
});
});
显然,我创建的
dynamo.get()
的模拟没有被
dbService.getItem()
使用,因为
dbService.getItem()
完全拥有自己对
DocumentClient
对象依赖的实例化


我应该将
DocumentClient
传递到我的
getItem()
函数中,还是有更好的方法?

DI是最好的方法,它将使代码更易于测试,具有更好的可伸缩性,并使模块解耦。但是,如果您想
要求
模块作为依赖项,您仍然可以存根
aws sdk
模块。单元测试解决方案:

dbService.js

const AWS=require('AWS-sdk');
异步函数getItem(){
const dynamo=new AWS.DynamoDB.DocumentClient();
变量参数={
/*无关的*/
};
试一试{
返回等待dynamo.get(params.promise();
}捕捉(错误){
返回错误;
}
}
exports.getItem=getItem;
dbService.test.js

const sinon=require('sinon');
const AWS=require('AWS-sdk');
const expect=require('chai')。expect;
description('dbService:When database return a record',function(){
之后(()=>{
sinon.restore();
});
它('应具有预期值',异步函数(){
const-mDynamo={get:sinon.stub().returnsThis(),promise:sinon.stub().resolves({Item:'an Item'})});
const mDocumentClient=sinon.stub(AWS.DynamoDB,'DocumentClient')。returns(mDynamo);
const dbService=require('./dbService');
const actual=await dbService.getItem();
expect(实际项目).to.be.equal(项目);
sinon.assert.calledOnce(mDocumentClient);
sinon.assert.calledWithJustice(mDynamo.get,{});
sinon.assert.calledOnce(mDynamo.promise);
});
它('should return error',async()=>{
const mError=新错误(“网络”);
const-mDynamo={get:sinon.stub().returnsThis(),promise:sinon.stub().rejects(mError)};
const mDocumentClient=sinon.stub(AWS.DynamoDB,'DocumentClient')。returns(mDynamo);
const dbService=require('./dbService');
const actual=await dbService.getItem();
expect(react.message).to.be.eql('network');
sinon.assert.calledOnce(mDocumentClient);
sinon.assert.calledWithJustice(mDynamo.get,{});
sinon.assert.calledOnce(mDynamo.promise);
});
});
单元测试结果:

  dbService: When database returns a record
    ✓ Should have expected value
    ✓ should return error


  2 passing (26ms)

--------------|---------|----------|---------|---------|-------------------
File          | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
--------------|---------|----------|---------|---------|-------------------
All files     |     100 |      100 |     100 |     100 |                   
 dbService.js |     100 |      100 |     100 |     100 |                   
--------------|---------|----------|---------|---------|-------------------

在这种情况下,将
DocumentClient
传递到
getItem()
函数中是否是执行DI的正确方法?因此签名将变成
异步函数getItem(docClient)
@Ubunfu您是对的
getItem
函数应该依赖于抽象(接口),而不是具体