【问题标题】:Unit Testing Node JS API using Jest使用 Jest 对 Node JS API 进行单元测试
【发布时间】:2020-02-28 09:31:07
【问题描述】:

我正在尝试通过使用 jest.fn(() => Promise.resolve(["FAQ 1"])); 模拟 DB 调用来为 NodeJS API 编写单元测试用例

我的 API 工厂文件是这样的:

const getFAQ=(request,reply)=>{

faqs.findByCondition(request.params.filter,success=>{
    reply(Response.sendResponse(true, success, ResponseMessages.SUCCESS, StatusCodes.OK));
 }, error => {
    log.error('ERROR : ', error);
         reply(Response.sendResponse(false, error, ResponseMessages.ERROR, 400));
    });

};

我的模型 JS 包含 findByCondition() 是这样的:

findByCondition = (condition, success_callback, error_callback) => {
        "use strict";
        faq.find(condition, (err, docs) => {
            if (err) {
                error_callback(err);
            } else {
                success_callback(docs);
            }
        });
    }

我尝试编写单元测试用例如下:

describe("test cases for FAQ Factory", () => {
    utils.callAPI = jest.fn(() => 'test')

    test('getFAQ Success Case', (done) => {
        const request = {
            params: {
                filter: 'all'
            },
            headers: {
                authorization: 'asfasfasdfas'
            }
        }
        faqModel.findByCondition = jest.fn(() => Promise.resolve(["FAQ 1"]));
        faqFactory.getFAQ(request, (result) => {
            expect(result).toBeDefined();
            expect(result.status_code).toBe(200);
        })
    })
});

我能够成功运行测试用例,但代码覆盖率未涵盖成功或错误回调

但如果我将我的 API Factory 更改为这样的东西,同样的测试用例也可以工作:

const getFAQ = (request, reply) => {
  faqs.findByCondition(request.params.filter).then(success => {
    reply(Response.sendResponse(true, success, ResponseMessages.SUCCESS, StatusCodes.OK));
  }).catch(error => {

    log.error('ERROR : ', error);
    reply(Response.sendResponse(false, error, ResponseMessages.ERROR, 400));
  });
};

有什么方法可以让我编写测试用例以覆盖成功/错误回调?

【问题讨论】:

    标签: javascript node.js unit-testing jestjs


    【解决方案1】:

    如果您想测试这两种情况并将您的回调传递给getFAQ,基本上您必须覆盖findByCondition

    为了更清楚地表达我的意思,我对其进行了一些简化。

    const getFAQ = (request, reply) => {
      faqs
        .findByCondition(request.params.filter)
        .then(success => {
          reply(true);
        })
        .catch(error => {
          reply(false);
        });
    };
    
    const faqs = {
      findByCondition: () => {
        return Promise.resolve();
      }
    };
    
    it("works", () => {
      jest.spyOn(faqs, `findByCondition`).mockResolvedValue({});
      getFAQ({ params: { filter: "hello" } }, reply => {
        expect(reply).toBe(true);
      });
    });
    
    it("doesn't work", () => {
      jest.spyOn(faqs, `findByCondition`).mockRejectedValue(new Error(`This fails because of error`));
      getFAQ({ params: { filter: "hello" } }, reply => {
        expect(reply).toBe(false);
      });
    });
    
    
    

    你可以看到here

    【讨论】:

    • 是的..这个解决方案有效。但我不允许在工厂更改实际的findbyCondition()
    • 你不必这样做,你可以用jest.spyOn.... 覆盖它我刚刚制作了findByCondition,因为我需要参考
    • 我已经覆盖了测试文件中的函数并且它可以工作。但是,当我看到为工厂生成的代码覆盖率报告时,我可以看到代码工厂代码没有被覆盖,因为我们在测试文件中覆盖了相同的代码。有没有其他方法可以修改我们的测试用例以提高代码覆盖率?
    【解决方案2】:

    更新: 我通过使用 mockingoose 库找到了一个解决方案,将我的测试用例编写如下:

    test("test to getFAQ Success", async (done) => {
            const request = {
                params: {
                    filter: 'all'
                },
                headers: {
                    authorization: testData.authorization
                }
            }
            mockingoose(faqModel.faq).toReturn([], 'find');
            const result = await promisify(faqFactory.getFAQ, request);
            expect(result).toBeDefined();
            expect(result.status).toEqual(200);
            done();
        })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-26
      • 2020-12-30
      • 2020-11-12
      • 2020-12-28
      • 1970-01-01
      • 2019-05-16
      • 2021-09-16
      • 2017-08-23
      相关资源
      最近更新 更多