javascript - 使用 $http 请求的 AngularJS 单元测试永远不会触发 .then() 回调

标签 javascript angularjs json karma-jasmine

我正在尝试使用单独的 json 文件中的模拟响应运行单元测试。当我使用 $q 返回在我的 OpsService 中手动解决的 promise 时,测试工作正常,但是当我试图将它们变成实际的 $http 请求以返回实际的 json 文件时,它们不再有效。

编辑:我已经尝试过 $httpBackend.flush()$rootScope.$apply()$rootScope.$digest() 但这些似乎都无法解决 promise 。

我的服务:

OpsService.service('OpsService', function ($q, $http) {

    this.get = {
        bigTen : function () {
            // var defer = $q.defer();
            // defer.resolve({"data":{"alltime":125077,"record":{"date":"2016-07-19","count":825},"today":281}});
            // return defer.promise;

            return $http({
                method: 'GET',
                url: '/jsonMocks/api/big-ten.json'
            }).then(function (response) {
                console.log('bigTen data');
                console.log(response);
                return response;
            }, function (error) {
                console.log('ERROR');
                console.log(error);
            });
        },

        dashboardData : function () {
            console.log('blahhhhh');
            return $http({
                method: 'GET',
                url: '/jsonMocks/api/dashboard-data.json'
            }).then(function (response) {
                console.log('dasbhoard data');
                console.log(response);
                return response;
            }, function (error) {
                console.log('ERROR');
                console.log(error);
            });
        }
    };

    return this;
});

我的 Controller :

homeModule.controller('HomeController', function ($scope, OpsService) {
    var ctrl = this;
    ctrl.loading = {
        topMetrics: true,
        dashboardData: true
    };

    function init() {
        ctrl.topMetricData();

        ctrl.getDashboardData();

        ctrl.initialized = true;
    }

    ctrl.topMetricData = function () {
        ctrl.loading.topMetrics = true;
        console.log('in topMetricData()');
        return OpsService.get.bigTen().then(function (bigTen) {
            console.log('bigTenControllerCallback');

            ctrl.loading.topMetrics = false;
            return bigTen;
        });
    };

    ctrl.getDashboardData = function () {
        ctrl.loading.dashboardData = true;
        console.log('in getDashboardData()');
        return OpsService.get.dashboardData().then(function (response) {
            console.log('getDashboardDataController Callback');

            ctrl.loading.dashboardData = false;
            return dashboardData;
        });
    };

    init();
});

我的测试:

describe('home section', function () {
    beforeEach(module('ngMockE2E'));
    beforeEach(module('templates-app'));
    beforeEach(module('templates-common'));
    beforeEach(module('LROps.home'));

    var $rootScope, $scope, $httpBackend, createController, requestHandler;

    beforeEach(inject(function($injector, _$rootScope_, _$controller_, _OpsService_) {
        $rootScope = _$rootScope_;

        $httpBackend = $injector.get('$httpBackend');

        var bigTenJson = readJSON('jsonMocks/api/big-ten.json');
        console.log(bigTenJson);
        $httpBackend.when('GET', '/jsonMocks/api/big-ten.json')
            .respond(200, { data: bigTenJson });
        // .respond(200, { data: 'test1' });

        var dashboardDataJson = readJSON('jsonMocks/api/dashboard-data.json');
        console.log(dashboardDataJson);
        $httpBackend.when('GET', '/jsonMocks/api/dashboard-data.json')
            .respond(200, { data: dashboardDataJson });
        // .respond(200, { data: 'test2' });

        var $controller = _$controller_;
        createController = function() {
            $scope = $rootScope.$new();
            return $controller('HomeController', {
                $scope : $scope,
                OpsService : _OpsService_
            });
        };
    }));

    afterEach(function() {
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    });

    it('should retrieve big ten data', inject(function () {
        $httpBackend.expect('GET', '/jsonMocks/api/big-ten.json');
        $httpBackend.expect('GET', '/jsonMocks/api/dashboard-data.json');

        // Controller Setup
        var ctrl = createController();

        // Initialize
        $rootScope.$apply();
        $rootScope.$digest();

        expect(ctrl.topMetrics.display.messages.count).toEqual(745);
    }));

});

所以,我的 console.log() 都没有在 .then() 回调中触发。如果我改回返回一个 $q.defer().resolve(response).promise 对象,它似乎工作正常。

注意:我正在使用 karma-read-json 来读取 JSON 文件并在我的测试中做出相应的响应。据我所知,它们被正确阅读,只是 promise 没有得到解决,所以 .then() 回调可以执行。

最佳答案

首先,每个断言请求都应该是模拟请求。请求应该用 $httpBackend.flush() 刷新,它触发一个摘要,$rootScope.$apply()$rootScope.$digest() (它们相互重复)不应该被调用。

第二件事是它不应该在 Controller 规范中完成! Controller 是一个依赖于服务的独立单元,它应该与模拟服务隔离测试。 OpsService 是一个不同的单元。

it('should retrieve big ten data', inject(function () {
    $httpBackend.expect('GET', '/jsonMocks/api/big-ten.json').respond(200, ...);
    $httpBackend.expect('GET', '/jsonMocks/api/dashboard-data.json').respond(200, ...);

    OpsService.get.bigTen().then(function (result) {
       expect(result)...
    }, function (err) {
       throw err;
    });
    OpsService.get.dashboardData()...

    $httpBackend.flush();
}));

it('should test a controller', inject(function () {
    var OpsServiceMock = { get: {
       bigTen: jasmine.createSpy().and.returnValue(...),
       dashboardData: jasmine.createSpy().and.returnValue(...)
    } };

    $scope = $rootScope.$new();

    var ctrl = $controller('HomeController', {
        $scope : $scope,
        OpsService : OpsServiceMock 
    });

    $rootScope.$digest();

    expect(OpsServiceMock.get.bigTen).toHaveBeenCalled();
    expect(OpsServiceMock.get.dashboardData).toHaveBeenCalled();
    expect...
}));

关于javascript - 使用 $http 请求的 AngularJS 单元测试永远不会触发 .then() 回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39021000/

相关文章:

javascript - 我想知道如何在 Jquery 加载 json 文件时在本地测试页面?

javascript - 加入 bookshelf.js

javascript - Mongoose:更新文档时转换为日期失败

javascript - React 中的类分配

javascript - 以 Angular 2 设置路线

javascript - 如何在 Sails.js 中为自定义路由启用 CORS

javascript - 从 ng-repeat 访问父 Controller

javascript - 有没有办法获取 JavaScript 的执行顺序以进行调试

java - JSON 转换问题

PHP JSON 解析出现错误