简体   繁体   中英

Mock call in Typescript in unit test using only Mocha

I have the following method:

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
      }
}

where the ObjectDal class is:

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;
    }
}

I have to write an unit test for the getObject() method using only Mocha...

This is the begining of the 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);
        });
    });
});

But in this case I would have to call the method from the ObjectDal class...

How can I mock the call to the get() method using only Mocha?

I found answers with Sinon, or Mocha with Sinon and/or Chai... but nothing with only Mocha...

Proxies might be the way to go for you. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

You could mok methods by using a Proxy like so:

 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); }); }); });

If you ONLY want to mok the ObjectDal.get method, you might want to override the prototype and recover it afterwards:

 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); }); }); });

You could also override the ObjectDal with a Proxy and implement the construct handler to return a dummy ObjectDal , but this might be more tricky, since you are working with modules.

Testing is feedback, not just on whether or not your code works as advertised but even more crucially on the quality of your design .

The fact that you are having trouble writing the tests is your first sign you did something sub-optimal in the implementation. What you want is this :

export class ObjectBL {
  constructor (dal) {
      this.dal = dal;
  }

  async getObject(id) {
      try {
          let result = await this.dal.get(id);

          return result;

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

...and now the dependency is clear rather than implicit and will show up in editor tooltips, is more amenable to static analysis, etc. And it solves your problem: now you can mock it easily for testing, no further libraries needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM