首页 > 解决方案 > 使用 Jest 模拟函数内部的类

问题描述

我正在测试一个控制器,它调用了一个像模型一样工作的类。

const getAllProducts = (req, res) => {
    const products = new ProductModel().getAll();

    res.status(200)
    res.send(products)
}
class ProductModel {
    constructor(name, brand) {
        this.id = null;
        this.name = name;
        this.brand = brand;
    }

    getAll() {
        const rawData = fs.readFileSync('./products.json');
        const products = JSON.parse(rawData);

        return products;
    }
}

问题是,我想通过模拟模型来测试控制器,因此不需要调用它(或者我应该只模拟fs部分,不确定)。

我看到了很多与函数内部模拟函数相关的东西(使用spyOnand jest.mock),但没有与类有关。

标签: javascriptnode.jsunit-testingexpressjestjs

解决方案


通常,您需要模拟/存根对正在测试的方法的直接依赖。对于您的情况,该getAllProducts功能测试不足,因此您需要模拟类getAll方法ProductModel

例如

controller.js

import { ProductModel } from './productModel';

export const getAllProducts = (req, res) => {
  const products = new ProductModel('github', 'reddit').getAll();

  res.status(200);
  res.send(products);
};

productModel.js

export class ProductModel {
  constructor(name, brand) {
    this.id = null;
    this.name = name;
    this.brand = brand;
  }

  getAll() {
    const rawData = fs.readFileSync('./products.json');
    const products = JSON.parse(rawData);

    return products;
  }
}

controller.test.js

import { getAllProducts } from './controller';
import { ProductModel } from './productModel';

describe('61966593', () => {
  it('should pass', () => {
    const mData = { data: [1, 2, 3] };
    const getAllSpy = jest.spyOn(ProductModel.prototype, 'getAll').mockReturnValueOnce(mData);
    const mReq = {};
    const mRes = { status: jest.fn().mockReturnThis(), send: jest.fn() };
    getAllProducts(mReq, mRes);
    expect(getAllSpy).toBeCalledTimes(1);
    expect(mRes.status).toBeCalledWith(200);
    expect(mRes.send).toBeCalledWith({ data: [1, 2, 3] });
    getAllSpy.mockRestore();
  });
});

单元测试的结果:

 PASS  stackoverflow/61966593/controller.test.js (9.078s)
  61966593
    ✓ should pass (4ms)

-----------------|---------|----------|---------|---------|-------------------
File             | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------------|---------|----------|---------|---------|-------------------
All files        |      80 |      100 |      75 |   78.57 |                   
 controller.js   |     100 |      100 |     100 |     100 |                   
 productModel.js |      70 |      100 |   66.67 |   66.67 | 9-12              
-----------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        10.273s

推荐阅读