gpt4 book ai didi

unit-testing - SailsJS : How to properly unit test controllers?

转载 作者:行者123 更新时间:2023-12-03 15:05:16 30 4
gpt4 key购买 nike

一直在使用 Sails.js,但在为 Controller 设计 Jasmine 单元测试时遇到了麻烦。如果这很明显,请原谅我的无知,因为在过去的 3-4 个月里我才深入研究 JavaScript 开发。

在过去的框架(特别是 ASP .Net MVC)中,我们有一些库来模拟 Controller 可能必须的任何依赖关系,例如,外部服务(通过依赖注入(inject))。我有点想用 Sails.js 实现相同级别的单元可测试性,以便我们实现适当的“单元”测试。具体来说,就我而言,我有一个依赖于服务对象的 Controller 操作——我只是想模拟该服务的响应。

但是,我有一段时间让这个 Jasmine 单元测试运行(使用 jasmine-node 插件)。下面是 Controller 及其单元测试的代码。我现在得到的是:

  • 应用 对象似乎无法在 afterEach()
  • 中解析
  • 对 spy 和测试级变量的断言失败了。

  • 我在单元测试中明显遗漏了什么明显的东西吗?代码如下。感谢您的任何意见!

    用户 Controller .js
    var Battlefield4Service = require('../services/battlefield4Service');
    module.exports = {
    /**
    * /user/bf4stats
    */
    bf4Stats: function (req, res) {
    var userName = req.param('userName');
    var platform = req.param('platform');
    var service = new Battlefield4Service();
    service.getPlayerInfo(userName, platform,
    function (data) {
    // Success callback
    res.json(data);
    });
    }
    };

    UserController.spec.js
    var Sails = require('sails');
    var userController = require('./UserController');
    var FPSStatsDTO = require('../dto/fpsStatsDTO');

    describe('UserController', function() {

    // create a variable to hold the instantiated sails server
    var app, req, res, rawObject, json;

    // Setup mocked dependencies
    beforeEach(function() {

    // Lift Sails and start the server
    Sails.lift({
    log: {
    level: 'error'
    }
    }, function(err, sails) {
    app = sails;
    //done(err, sails);
    });

    // Mocked Battlefield4Service
    Battlefield4Service = {
    getPlayerInfo: function (userName, platform, success) {
    var dto = new FPSStatsDTO();
    dto.userName = userName;
    dto.platform = platform;
    success(dto);
    }
    };

    // req and res objects, mock out the json call
    req = {
    param: function(paramName) {
    switch (paramName) {
    case 'userName':
    return 'dummyUser';
    case 'platform':
    return 'dummyPlatform';
    }
    }
    };
    res = {
    json: function(object) {
    rawObject = object;
    json = JSON.stringify(object);
    return json;
    }
    };

    // Deploy 007
    spyOn(req, 'param');
    spyOn(res, 'json');
    spyOn(Battlefield4Service, 'getPlayerInfo');
    });

    afterEach(function(){
    app.lower();
    });

    it('Should call the Battlefield 4 Service', function() {

    // Call the controller
    userController.bf4Stats(req, res);

    // Assertions
    expect(req.param).toHaveBeenCalled();
    expect(res.json).toHaveBeenCalled();
    expect(Battlefield4Service.getPlayerInfo).toHaveBeenCalledWith(req.param('userName'), req.param('platform'));
    expect(rawObject.userName).toEqual(req.param('userName'));
    expect(rawObject.platform).toEqual(req.param('platform'));
    expect(json).toNotBe(null);
    expect(json).toNotBe(undefined);
    });
    });

    最佳答案

    更新

    进一步考虑应用程序架构,我不需要测试 Sails.js Controller 的请求/响应——在这个应用程序的上下文中, Controller 非常愚蠢,因为它们只是传递 JSON 对象.所以,我真正需要测试的是我的服务正在将外部 API 的对象转换为我的应用程序的内部 DTO,该 DTO 将用作 JSON 返回。换句话说,对我来说,测试实际翻译比确保 Controller 通过它更重要,我们可以放心地假设情况总是如此。

    话虽如此,我将我的单元测试套件从 Jasmine 切换到 Chad 建议的 Mocha、Chai 和 Sinon 组合。 imocha 中的异步钩子(Hook)看起来更干净,imo。我使用的一个添加库是 Nock ,一个旨在模拟 HTTP 请求的库,因此我可以拦截我的服务类对 API 的调用并返回一个 stub 对象。

    所以,回顾一下,我放弃了对 Controller 的单元测试,因为它对我的用例来说是多余的。我需要测试的重要功能是将外部 API 的对象转换为我的内部应用程序的等效 DTO。

    下面的单元测试用于实际服务。请注意,此特定测试不需要 Sinon 进行 stub /模拟,因为 Nock 为我处理了这些:

    var Sails = require('sails');
    var sinon = require('sinon'); // Mocking/stubbing/spying
    var assert = require('chai').assert; // Assertions
    var nock = require('nock'); // HTTP Request Mocking
    var constants = require('../constants/externalSystemsConstants');
    var Battlefield4Service = require('./battlefield4Service');

    describe('External Services', function () {

    // create a variable to hold the instantiated sails server
    var app, battlefield4Service;

    // Global before hook
    before(function (done) {

    // Lift Sails and start the server
    Sails.lift({

    log: {
    level: 'error'
    }

    }, function (err, sails) {
    app = sails;
    done(err, sails);
    });
    });

    // Global after hook
    after(function (done) {
    app.lower(done);
    });

    describe('Battlefield 4 Service', function () {
    var userName, platform, kills, skill, deaths, killAssists, shotsHit, shotsFired;

    before(function () {

    // Mock data points
    userName = 'dummyUser';
    platform = 'ps3';
    kills = 200;
    skill = 300;
    deaths = 220;
    killAssists = 300;
    shotsHit = 2346;
    shotsFired = 7800;

    var mockReturnJson = {
    player: {
    name: userName,
    plat: platform
    },
    stats: {
    kills: kills,
    skill: skill,
    deaths: deaths,
    killAssists: killAssists,
    shotsHit: shotsHit,
    shotsFired: shotsFired
    }
    };

    // Mock response from BF4 API
    battlefield4Service = nock('http://' + constants.BF4_SERVICE_URI_HOST)
    .get(constants.BF4_SERVICE_URI_PATH.replace('[platform]', platform).replace('[name]', userName))
    .reply(200, mockReturnJson);
    });

    it('Should translate BF4 API data to FPSStatsDTO', function (done) {
    var service = new Battlefield4Service();
    service.getPlayerInfo(userName, platform, function (fpsStats) {
    assert(fpsStats !== null);
    assert(fpsStats !== undefined);
    assert(fpsStats.kills === kills, 'kills');
    assert(fpsStats.deaths === deaths, 'deaths');
    assert(fpsStats.killAssists === killAssists, 'deaths')
    assert(fpsStats.kdr === kills / deaths, 'kdr');
    assert(fpsStats.shotsFired === shotsFired, 'shotsFired');
    assert(fpsStats.shotsHit === shotsHit, 'shotsHit');
    assert(fpsStats.shotsAccuracy === shotsHit / shotsFired, 'shotsAccuracy');
    assert(fpsStats.userName === userName, 'userName');
    assert(fpsStats.platform === platform, 'platform');
    done();
    });
    });
    });
    });

    关于unit-testing - SailsJS : How to properly unit test controllers?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21918545/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com