首页 > 解决方案 > 单元测试中 Typescript 中的模拟调用仅使用 Mocha

问题描述

我有以下方法:

import { ObjectDal } from "./ObjectDal";

export class ObjectBL {
  async getObject(id) {
      try {
          let dal = new ObjectDal();

          let result = await dal.get(id);

          return result;

      } catch (err) {
          // log the error
      }
}

课程在哪里ObjectDal

export class ObjectDal {
    async get(id) {
        // open connection to db
        // make a query based on id

        // put the result in a `result` variable

        return result;
    }
}

我必须为仅使用Mocha的getObject()方法编写单元测试......

这是UT的开始:

const assert = require('assert');
const ObjectBL = require("../ObjectBL");

describe('Something', () => {
    describe('...', () => {
        it('getObject_GetsObjectUsingID_True', async () => {
            // arange
            let id = "123456789101";
            let expected = {
                "name": "ana",
                "hasApples": true
            };

            let test = new ObjectBL.ObjectBL();

            let result = await test.getObject(id);

            assert.deepStrictEqual(result, expected);
        });
    });
});

但在这种情况下,我将不得不从ObjectDal类中调用该方法......

如何get()仅使用 Mocha 模拟对方法的调用?

我用 Sinon 找到了答案,或者用 Sinon 和/或 Chai 找到了 Mocha……但只有 Mocha 什么都没有……

标签: javascripttypescriptunit-testingmocha.js

解决方案


代理可能是适合您的方式。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

您可以使用这样的代理来 mok 方法:

const assert = require('assert');
const ObjectBL = require("../ObjectBL");

describe('Something', () => {
    describe('...', () => {
        it('getObject_GetsObjectUsingID_True', async () => {
            // arange
            let id = "123456789101";
            let expected = {
                "name": "ana",
                "hasApples": true
            };

            let test = new ObjectBL.ObjectBL();
            
            const handler = {
              get: function(obj, prop) {
                // mok the getObject method
                if(prop === 'getObject'){
                  return () => {
                    return Promise.resolve({
                        "name": "ana",
                        "hasApples": true
                    });
                   }
                } else {
                  return obj[prop];
                }
              }
            };
            const p = new Proxy(test, handler);

            let result = await p.getObject(id);

            assert.deepStrictEqual(result, expected);
        });
    });
});

如果您只想修改该ObjectDal.get方法,则可能需要覆盖原型并在之后恢复它:

const assert = require('assert');
const ObjectBL = require("../ObjectBL");
const ObjectDal = require("../ObjectDal");

describe('Something', () => {
    describe('...', () => {
        it('getObject_GetsObjectUsingID_True', async () => {
            // arange
            let id = "123456789101";
            let expected = {
                "name": "ana",
                "hasApples": true,
            };
            
            const proto = Object.getOwnPropertyDescriptor(ObjectDal, 'prototype').value;
            
            const backup = proto.get;
            proto.get = () => {
              return Promise.resolve({
                  "name": "ana",
                  "hasApples": true,
              });
            }

            let test = new ObjectBL.ObjectBL();

            let result = await test.getObject(id);
            
            ObjectDal.prototype.get = backup;
            
            assert.deepStrictEqual(result, expected);
        });
    });
});

您还可以使用 Proxy 覆盖ObjectDal并实现construct处理程序以返回 dummy ObjectDal,但这可能更棘手,因为您正在使用模块。


推荐阅读