使用服务方法的单元测试节点js控制器的最佳方法是什么

Rak*_*mar 10 javascript unit-testing node.js jasmine

My Controller =>下面的控制器正在使用reqpoertService.getFiles方法,该方法本身使用外部API来调用数据.

function getFiles(req, res) {
    reportService.getFiles({
        fromDate: req.query.fromdate,
        endDate: req.query.enddate,
        fileTypes: req.query.filetypes || [],
        fileStatus: req.query.filestatus || []
    })
    .then(data => {
       logger.info('-> reportService.getFiles :: Successfully fetched data',
                   resolveLogger({ statusCode: res.statusCode })
       );
       res.send(data);
   })
   .catch(err => {
       logger.error('<- OOPS :: reportService.getFiles fail to fetch data');
       res.status(statusCodes.INTERNAL_SERVER_ERROR).send({});
       logger.error('<- ERROR', resolveLogger({
           statusCode: res.statusCode,
           errMessage: err.message,
           errorStack: err
       }));
   });
}
Run Code Online (Sandbox Code Playgroud)

记者服务

function getFiles() {
    return new Promise((resolve, reject) => {
        requestPromise(options)
            .then(data => {
                var duration = new Date - start;
                logger.info(resolveLogger({
                    duration: duration + 'ms',
                    reqUrl: options.url,
                    bodyLengh: data && data.length
                }));
                logger.info('<= Request complete successfully.');
                var resData = JSON.parse(data);
                resolve(resData);
            })
            .catch(error => {
                logger.error('=> Request failed for URL:', options.url);
                reject(error);
            });
    });
}
Run Code Online (Sandbox Code Playgroud)

我的单元测试方法测试上面的控制器

it('METHOD: getFiles -> should response 500 without data', done => {
    nock('http://localhost:1708/fakeapi')
        .get('/files')
        .reply(statusCodes.INTERNAL_SERVER_ERROR);

    const res = buildResponse();
    const req = httpMocks.createRequest({
        method: 'GET',
        url: '/api/submitted-data/1/files'
    });

    res.on('end', function () {
        var data = res._getData();
        expect(data).toEqual({});
        expect(statusCodes.INTERNAL_SERVER_ERROR).toBe(res.statusCode);
        done();
        nock.cleanAll();
    });

    reporterController.getFiles(req, res);
});
Run Code Online (Sandbox Code Playgroud)

有人可以告诉我,我所遵循的方法是可以接受的,还是有更好的方法来进行单元测试.因为我是初学者进行单元测试.

Mat*_*jeS 6

我认为你的方法是正确的。你的测试应该尽可能地与实现分离。所以你的测试代码不应该真正知道你是如何实现你的代码的。它只关心当您到达端点时,结果是否符合预期。您想模拟代码的外部部分,即在您运行测试(例如外部 API)时不会执行的代码。您可以模拟外部 API 的某些响应,以便您可以编写测试来覆盖这些类型的场景,然后根据需要处理它们。

ThoughtWorks 的这篇文章对解释这种测试方法很有帮助:https : //www.thoughtworks.com/insights/blog/mockists-are-dead-long-live-classicists

我还建议观看此视频标题 Ian Cooper:TDD 哪里出错了:https : //vimeo.com/68375232

我很欣赏我的建议有点高,所以简而言之,我认为您的测试应该如下所示:

  1. 建立测试的上下文,设置数据等。因此,在您的情况下,请确保文件存在(如果来自外部 api,这可能是模拟响应)
  2. 为您的外部 api 设置模拟(以覆盖外部 api 是否超时、关闭、401、500 等)。
  3. 调用你的api
  4. 断言您的 api 端点返回的结果

然后,您可以使用不同的测试来检查外部 api 返回的不同响应。