ExpressJS RESTapi写单元测试以进行CRUD操作

时间:2020-03-03 06:36:58

标签: javascript node.js unit-testing express jestjs

我有一个RESTapi,我需要为此RESTapi编写单元测试。这几乎是CRUD操作。 样本餐厅管理员就是这样。

const db = {restaurant}

async function create(req, res) {
   try {
      await db.restaurant.create(req.body);
      res.sendStatus(200)
   } catch (error) {
      res.sendStatus(500)
   }
}

async function read(req, res) {
   try {
      const data = await db.restaurant.findAll();
      res.send(200).json(data)

   } catch (error) {
      res.sendStatus(500)
   }
}

async function update(req,res) {
   try {
      await db.restaurant.update({
         name:'KFC'
      },{
         where:{
            id:req.params.id
         }
      })
   } catch (error) {
      res.sendStatus(500)
   }
}

module.exports = {
   create,
   read,
   update
}

我想为此控制器编写单元测试。如果我写了,我应该检查这些功能吗?我真的很困惑,我对这些功能的单元测试有什么期望? 我选择JEST作为测试框架。

1 个答案:

答案 0 :(得分:0)

这是单元测试解决方案:

index.js

const db = require('./db');

async function create(req, res) {
  try {
    await db.restaurant.create(req.body);
    res.sendStatus(200);
  } catch (error) {
    res.sendStatus(500);
  }
}

async function read(req, res) {
  try {
    const data = await db.restaurant.findAll();
    res.send(200).json(data);
  } catch (error) {
    res.sendStatus(500);
  }
}

async function update(req, res) {
  try {
    await db.restaurant.update(
      {
        name: 'KFC',
      },
      {
        where: {
          id: req.params.id,
        },
      },
    );
  } catch (error) {
    res.sendStatus(500);
  }
}

module.exports = {
  create,
  read,
  update,
};

db.js

const db = {
  restaurant: {
    async create() {},
    async findAll() {},
    async update() {},
  },
};

module.exports = db;

index.test.js

const { create, read, update } = require('./');
const db = require('./db');

jest.mock('./db');

describe('60501363', () => {
  describe('#create', () => {
    it('should create correctly', async () => {
      const mReq = { body: {} };
      const mRes = { sendStatus: jest.fn() };
      jest.spyOn(db.restaurant, 'create').mockResolvedValueOnce({});
      await create(mReq, mRes);
      expect(db.restaurant.create).toBeCalledWith({});
      expect(mRes.sendStatus).toBeCalledWith(200);
    });
    it('should handle error if create failure', async () => {
      const mReq = { body: {} };
      const mRes = { sendStatus: jest.fn() };
      const mError = new Error('network');
      jest.spyOn(db.restaurant, 'create').mockRejectedValueOnce(mError);
      await create(mReq, mRes);
      expect(mRes.sendStatus).toBeCalledWith(500);
    });
  });

  describe('#read', () => {
    it('should read', async () => {
      const mReq = {};
      const mRes = { send: jest.fn().mockReturnThis(), json: jest.fn() };
      jest.spyOn(db.restaurant, 'findAll').mockResolvedValueOnce([]);
      await read(mReq, mRes);
      expect(db.restaurant.findAll).toBeCalledTimes(1);
      expect(mRes.send).toBeCalledWith(200);
      expect(mRes.json).toBeCalledWith([]);
    });
  });

  describe('#update', () => {
    it('should update correctly', async () => {
      const mReq = { params: { id: 1 } };
      const mRes = {};
      jest.spyOn(db.restaurant, 'update').mockResolvedValueOnce({});
      await update(mReq, mRes);
      expect(db.restaurant.update).toBeCalledWith({ name: 'KFC' }, { where: { id: 1 } });
    });
  });
});

带有覆盖率报告的单元测试结果:

 PASS  stackoverflow/60501363/index.test.js (11.289s)
  60501363
    #create
      ✓ should create correctly (6ms)
      ✓ should handle error if create failure (2ms)
    #read
      ✓ should read (1ms)
    #update
      ✓ should update correctly

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |   84.62 |      100 |      50 |   83.33 |                   
 db.js    |     100 |      100 |       0 |     100 |                   
 index.js |   81.82 |      100 |     100 |      80 | 17,34             
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       4 passed, 4 total
Snapshots:   0 total
Time:        13.076s

源代码:https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60501363