javascript - Controller 的 Mocha 单元测试解决了来自服务的 promise

标签 javascript node.js unit-testing controller mocha.js

我有 Controller :

function(req, res) {
    // Use the Domain model to find all domain
    CIO.find(function(err, CIOs) {
        if (err) {
            response = responseFormat.create(false, "Error getting CIOs", err, {});
            res.status(400).json(response);
        } else {

            var metrics = {
                "count": CIOs.length
            };

            // .then means it will wait for it to finish, then let you have the result


            var promises = [];

            for (i in CIOs) {
                promises.push(Analysis.structureMetrics(CIOs[i].toObject()))
            }

            var output = []
            var errors = []
            Q.allSettled(promises)
                .then(function(results) {


                    for (i in results) {
                        if (results[i].state === "rejected") {
                            console.log(results[i])
                            errors.push(results[i].reason.errors)
                            output.push(results[i].reason)
                        } else {
                            output.push(results[i].value)
                        }
                    }
                }).then(function() {
                    response = responseFormat.create(true, "List of all CIOs", output, metrics, errors);
                    res.status(200).json(response);
                })
        }
    });
};

和 cio.test 文件:

describe('/cio', function() {
    describe('GET', function() {

        //this.timeout(30000);
        before(function() {
            
        });

        it('should return response', function(done) {
            var response = http_mocks.createResponse({eventEmitter: require('events').EventEmitter})
            var request  = http_mocks.createRequest({
                method: 'GET',
                url: '/cio',
            })          
            //var data = JSON.parse( response._getData() );
            response.on('end', function() {
                response.statusCode.should.be.equal(400);
                done();
            
            })
            cioCtrl.getCIOs(request, response);
        });

     
    });
});

出现错误

Error: timeout of 10000ms exceeded. Ensure the done() callback is being called in this test

1>我已经尝试过增加时间,但不起作用。

2> 我发现 response.('end', function(){}) 没有被调用,但不确定为什么

如有任何帮助,我们将不胜感激。 谢谢!

最佳答案

单元测试的一个非常好的方法是使用 dependency injection .

为此,您的 Controller 文件应如下所示:

module.exports = class MyController {
  constructor(CIO) {
    this._CIO = CIO;
    this.handler = this.handler.bind(this);
  }

  handler(req, res) {
    // your code here using this._CIO
  }
};

与主文件相比,您创建 Controller 实例:

const MyController = require('./controllers/my-controller');

// require your CIO, or create instance...
const CIO = require('./CIO');

const myController = new MyController(CIO);

然后,您只需将 Controller 的实例或其处理函数传递到将使用它的地方。

使用这种方法可以让您进行良好的测试。 假设你的“它”看起来像这样:

it('should work', function(done) {
  const fakeCIO = { 
    find: function() {
      done();
    }
  };
  const myController = new MyController(fakeCIO);
  myController.handler();
});

测试技术之间的基本区别:

  • 单元测试 - 测试一个单元,它如何调用函数、进行赋值、返回值
  • 集成测试 - 将数据库添加到之前的测试中并检查它的存储/删除/更新方式
  • 端到端测试 - 您将 API 端点添加到之前的集成测试中,并检查整个流程的工作原理

更新:
使用异步/等待方法,您将能够使用 Controller 测试更多东西。假设修改如下:

async function(req, res) {
  try {
    const CIOs = await CIO.find();
    const metrics = {
      "count": CIOs.length
    };
    const promises = CIOs.map(el => Analysis.structureMetrics(el.toObject());

    for(const promise of promises) {
      const result = await promise();
      // do whatever you need with results
    }

  } catch(err) {
    const response = responseFormat.create(false, "Error getting CIOs", err, {});
    res.status(400).json(response);
  }

使用这种方法,在单元测试期间您还可以测试 Controller 调用方法:

  • responseFormat.create
  • 分析.结构指标
  • res.status
  • res.json
  • test catch 要执行的分支

这一切都是用假对象完成的。 当然,使用 OOP 不是强制性的,这只是一个习惯问题,您可以使用函数式风格做同样的事情,如 closures ,例如。

关于javascript - Controller 的 Mocha 单元测试解决了来自服务的 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45027659/

相关文章:

unit-testing - 如何对包含 dynamoDB 查询的 lambda 函数进行单元测试

javascript - 动态创建单选按钮并选择适当的按钮 Angularjs

java - 有没有办法在groovy中自动设置字符串中的Windows路径?

ajax - 从客户端查询时,带参数的 Express.js 路由会产生 404

unit-testing - Visual Studio 环境中 Jasmine 中的 Typescript 测试

database - 单元测试依赖于数据库的窗口服务

javascript - 通过 javascript 定义动画线的长度

javascript - 缺少移动导航栏 - github pages iridium 模板

javascript - 如何通过 JSON/JS 在 Jenkins 中为 CSRF 添加面包屑

javascript - Node 上的 server.js 文件在哪里