简体   繁体   English

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

[英]What is the best approach to unit test node js controller which using a service method

My Controller => below controller is using reqpoertService.getFiles method and that method itself using a external APIs to call the data. 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
       }));
   });
}

Reporter Service 记者服务

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

My Unit Test Approach to test above controller 我的单元测试方法测试上面的控制器

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

Can someone suggest me the approach I am following is acceptable or is there any better approach to do the unit test. 有人可以告诉我,我所遵循的方法是可以接受的,还是有更好的方法来进行单元测试。 As I am beginner to do the unit testing. 因为我是初学者进行单元测试。

I think your approach is on the right path. 我认为你的方法是在正确的道路上。 Your tests should be decoupled as much from the implementation as much as possible. 您的测试应尽可能多地与实现分离。 So your test code shouldn't really know how you've implemented your code. 因此,您的测试代码应该不知道您是如何实现代码的。 It just cares that when you hit your endpoints, the outcome is as expected. 它只关心当你点击你的终点时,结果是预期的。 You want to mock the external parts of your code, ie the code that won't execute when you run your test such as external APIs. 您希望模拟代码的外部部分,即在运行测试时不会执行的代码,例如外部API。 You can mock certain responses that the external APIs so you can write tests to cover those types of scenarios and then handle them as you want. 您可以模拟外部API的某些响应,以便您可以编写测试以涵盖这些类型的方案,然后根据需要处理它们。

This article from ThoughtWorks is quite helpful in explaining this approach to testing: https://www.thoughtworks.com/insights/blog/mockists-are-dead-long-live-classicists ThoughtWorks的这篇文章非常有助于解释这种测试方法: https//www.thoughtworks.com/insights/blog/mockists-are-dead-long-live-classicists

I'd also suggest watching this video title Ian Cooper: TDD where did it all go wrong: https://vimeo.com/68375232 我还建议观看这个视频节目Ian Cooper:TDD哪里出错了: https//vimeo.com/68375232

I appreciate my suggestion is a little high level so in short I think your test should look like: 我感谢我的建议有点高,所以总之我认为你的测试应该是这样的:

  1. establish the context of your test, setting up data etc. So in your case ensure a file exists (this could be mocked response if coming from an external api) 建立测试的上下文,设置数据等。所以在你的情况下确保存在一个文件(如果来自外部api,这可能是模拟的响应)
  2. set up mocking for your external apis (to cover if the external api times out, is down, 401, 500 etc). 为你的外部api设置模拟(如果外部api超时,则覆盖,401,500等)。
  3. call your api 打电话给你的api
  4. assert the result that your api endpoint returns 断言api端点返回的结果

You can then have different tests checking different responses that the external apis return. 然后,您可以使用不同的测试来检查外部api返回的不同响应。

I have one criticism of you unit test, and it is that you aren't using beforeAll/each to actually setup your test. 我对你的单元测试有一个批评,那就是你没有使用beforeAll / each来实际设置你的测试。

What I mean by this is: 我的意思是:

  • You can use the describe block in which the "it" is nested to declare variables that will be set during the test setup (beforeEach/All) and should be the ones that you actually "expect" during the "it". 您可以使用嵌套“it”的describe块来声明将在测试设置期间设置的变量(beforeEach / All),并且应该是您在“it”期间实际“期望”的变量。
  • The "it"s themselves should be cleaner and smaller, almost only being composed by expects. “它”本身应该更清洁,更小,几乎只是由期望组成。

Appart from that it looks good. 公寓从那看起来不错。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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