Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.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
Node.js 使用Sinon对服务模块进行模拟_Node.js_Unit Testing_Sinon_Sinon Chai - Fatal编程技术网

Node.js 使用Sinon对服务模块进行模拟

Node.js 使用Sinon对服务模块进行模拟,node.js,unit-testing,sinon,sinon-chai,Node.js,Unit Testing,Sinon,Sinon Chai,我已经进入了单元测试的阶段,老实说,网上的各种例子让我感到困惑。我对摩卡和柴有很好的了解,但西农是另一回事 所以我认为这是一个非常直接的设置。我有一个呼叫控制器的POST路由。此控制器与此类似(删除了一些基本验证代码) 所以它真正做的就是验证,然后用req创建一个用户对象,并将其传递给服务类。这个服务类只将数据传递给数据库类 const { addUserToDb } = require('../database/user.db'); const createUser = async (use

我已经进入了单元测试的阶段,老实说,网上的各种例子让我感到困惑。我对摩卡和柴有很好的了解,但西农是另一回事

所以我认为这是一个非常直接的设置。我有一个呼叫控制器的POST路由。此控制器与此类似(删除了一些基本验证代码)

所以它真正做的就是验证,然后用req创建一个用户对象,并将其传递给服务类。这个服务类只将数据传递给数据库类

const { addUserToDb } = require('../database/user.db');

const createUser = async (user) => {
  try {
    const createdUser = await addUserToDb(user);
    return createdUser;
  } catch (err) {
    throw new Error(err);
  }
};

module.exports = {
  createUser,
};
我不会显示数据库类,因为我想首先关注的是控制器,然后我希望自己可以完成其余的工作

根据我的理解,我应该测试函数。如果函数进行外部调用,我应该监视、模拟、存根该调用?我应该只监视、模拟或存根这个函数依赖项,如果其中一个依赖项 有自己的依赖项(就像上面的服务模块有数据库调用依赖项),这应该在另一个测试中执行吗?对不起,我想问几个问题来帮助我理解

总之,我创建了一个user.controller.test.js文件。我在这方面还没有取得很大进展,但这就是我目前所拥有的

const chai = require('chai');
const sinon = require('sinon');

const { expect } = chai;
const faker = require('faker');

const controller = require('../controllers/user.controller');
const service = require('../services/user.service');

const flushPromises = () => new Promise(setImmediate);

describe('user.controller', () => {
  describe('postUser', () => {
    beforeEach(() => {
        //I see a lot of code use a beforeEach, what should I be doing here?
    });

    it('should create a user when account_id and status params are provided', async () => {
      const req = {
        body: { account_id: faker.datatype.uuid(), status: 'true' },
      };

      const stubValue = {
        id: faker.datatype.id(),
        account_id: faker.datatype.uuid(),
        status: 'true',
        created_at: faker.date.past(),
        updated_at: faker.date.past(),
      };
      
    });
  });
});
如果我完全诚实的话,我对我应该在这里测试什么感到非常困惑。根据我的理解,我需要模仿我认为的服务模块

有人能提供一些关于我在这次测试中应该做什么的见解吗

非常感谢

更新


谢谢你的详细回复,我已经设法让一个间谍工作,这是向前迈出的一步。所以我想在我的服务模块上做一个测试,
createUser
方法

您可以看到,my
createUser
方法将用户对象作为参数,并将其传递给数据库模块,然后将其插入数据库,然后返回用户对象

因此,在测试我的服务类时,我需要模拟对数据库模块的调用

const chai = require('chai');
const sinon = require('sinon');

const { expect } = chai;
const faker = require('faker');

const service = require('../services/user.service');
const database = require('../database/user.db');

describe('user.service', () => {
  describe('createUser', () => {
    it('should create a user when user object is provided', async () => {
      const user = {
        id: faker.datatype.string(),
        status: 'true',
        created_at: faker.date.past(),
        updated_at: faker.date.past(),
      };
      const expectedUser = {
        id: user.id,
        status: user.status,
        created_at: user.created_at,
        updated_at: user.updated_at,
      };

      const mockedDatabase = sinon.mock(database);

      mockedDatabase.expects('addUserToDb').once().withArgs(expectedUser);
      await service.createUser(user);

      mockedDatabase.verify();
      mockedDatabase.restore();
    });
  });
});
当我测试这个时,我似乎得到了这个响应,它似乎仍然在将记录插入我的数据库

ExpectationError: Expected addUserToDb({
  id: 'yX7AX\\J&gf',
  status: 'true',
  created_at: 2020-06-03T03:10:23.472Z,
  updated_at: 2020-05-24T14:44:14.749Z
}, '[...]') once (never called)
      at Object.fail (node_modules\sinon\lib\sinon\mock-expectation.js:314:25)
  
  
你知道我做错了什么吗


谢谢

在我尝试之前,我想建议在任何地方删除
try/catch
块,我假设您在节点应用程序中使用expressJs,为此,请查看使用该路由器(而不是默认路由器)将自动捕获抛出的任何内容,您只需关注代码

以你为例,你会写:

const{addUserToDb}=require('../database/user.db');
const createUser=async(user)=>addUserToDb(user);
module.exports={
createUser,
};

const{createUser}=require('../services/user.service');
常量apiResponse=require('../helpers/apiResponse');
常量姿态=异步(请求、res)=>{
const{id:account_id,status}=res.body;
const result=await createUser({account_id,status});//在fn中设置日期
返回apiResponse.successResponseWithData(res,'用户添加',result.affectedRows);
};
module.exports={
姿态,
};
如果有一个错误,并且在路由的某个地方抛出了一个错误,那么您将在响应中收到一条带有错误的好消息


关于代码本身,阅读起来似乎要干净得多——记住代码是为人类编写的,机器甚至不在乎你如何命名变量。谢谢你的详细回答,我仍然有一些问题,不太清楚为什么。我在我的帖子上留下了更新,你知道为什么会发生这种情况吗?感谢您的服务,尝试做
db.addUserToDb(用户)
so,不分解
addUserToDb
,而是使用
const db=require('../database/user.db')-非常感谢。很长一段时间以来,我一直在努力解决这个问题,哇,这是一个简单的解决办法!我已将您的答案标记为正确,并将在2小时内给予奖金:-)非常感谢您的详细解释。这不是分数,只是为了帮助Stackoverflow的一位同事
ExpectationError: Expected addUserToDb({
  id: 'yX7AX\\J&gf',
  status: 'true',
  created_at: 2020-06-03T03:10:23.472Z,
  updated_at: 2020-05-24T14:44:14.749Z
}, '[...]') once (never called)
      at Object.fail (node_modules\sinon\lib\sinon\mock-expectation.js:314:25)