承诺的Angular服务单元测试失败

迈克·古德温

JSFiddle显示问题:

http://jsfiddle.net/ggvfwoeL/3/

我有一个涉及用于生成威胁的服务的Angular应用程序。使用nools规则引擎完成威胁生成该服务公开了一个generateForElement返回诺言的函数该函数如下所示(有关详细信息,请参见JSFiddle):

var Element = function (element) { this.type = element.attributes.type; }
var Threats = function () { this.collection = []; }    

    function generateForElement(element) {
           var threats = new Threats();
           var el = new Element(element);
           flow.getSession(threats, el).match();
           return $q.when(threats.collection);
    }

设置了规则引擎,以便当您generateForElement使用tm.Process类型的元素进行调用时,它会产生2种威胁。这是定义规则的代码(显然,这已经简化了很多,以使问题更清楚):

function initialiseFlow() {
        return nools.flow('Element threat generation', function (flow) {

            flow.rule('Spoofing Threat Rule', [
                [Element, 'el', 'el.type == "tm.Process"'],
                [Threats, 'threats']
            ], function (facts) {
                facts.threats.collection.push('Spoofing');
            });

            flow.rule('Tampering Threat Rule', [
                [Element, 'el', 'el.type == "tm.Process"'],
                [Threats, 'threats']
            ], function (facts) {
                facts.threats.collection.push('Tampering');
            });
        });
    }

当我在应用程序中手动测试时,我看到正在生成两种威胁。但是我的单元测试在这条线上失败了

expect(threats.length).toEqual(2);

有错误

Error: Expected 1 to equal 2.

因此,似乎仅生成了1种威胁。单元测试的定义是这样的:

describe('threatengine service', function () {

    var threatengine;
    var $rootScope;

    beforeEach(function () {

        angular.mock.module('app')

        angular.mock.inject(function (_$rootScope_, _threatengine_) {
            threatengine = _threatengine_;
            $rootScope = _$rootScope_;
        });

        $rootScope.$apply();
    });

    describe('threat generation tests', function () {

        it('process should generate two threats', function () {

            var element = { attributes: { type: 'tm.Process' }};
            var threats;
            threatengine.generateForElement(element).then(function (data) {
                threats = data;
            });
            expect(threats).toBeUndefined();
            $rootScope.$apply();
            expect(threats).toBeDefined();
            expect(threats.length).toEqual(2);
        });
    });
});

显然我在做错事。就像我说的那样,当我运行完整的应用程序时,我肯定会遇到2种威胁,这使我认为故障可能与单元测试有关,或者与我如何处理服务中的诺言有关,但我看不到。

为什么我的单元测试失败?

迈克尔·拉迪诺夫(Michael Radionov)

第一个问题是在flow.getSession(threats, el).match();您的代码中被同步调用的调用,但最初它似乎是异步的(我对nools不熟悉,但这里是docs)。因此,即使您将console.log两个规则都放置在处理程序中,您也会看到规则比后面的同步代码更晚地得到处理。解决方案是使用一个promise,该promise将.match()返回:

function generateForElement(element) {
    var threats = new Threats();
    var el = new Element(element);
    // handle async code via promises and resolve it with custom collection
    return flow.getSession(threats, el).match().then(function () {
      return threats.collection;
    });
}

另一个问题在测试文件中。那里,您也有一个异步代码,但是您像同步代码一样对其进行处理。请参阅Jasmine文档中的异步支持基本上,您必须告诉Jasmine测试是否异步,并在测试完成时通知它。

it('process should generate two threats', function (done) {
    // telling Jasmine that code is async ----------^^^

    var element = { attributes: { type: 'tm.Process' }};

    // this call is async
    threatengine.generateForElement(element).then(function (threats) {
        expect(threats).toBeUndefined();
        expect(threats).toBeDefined();
        expect(threats.length).toEqual(2);

        done(); // telling Jasmine that code has completed
    });

    // is required to start promises cycle if any
    $rootScope.$apply();
});

这是一个正在工作的JSFiddle

更新:

这是Jasmine 1.3的规格,它使用另一个API进行异步处理:

it('process should generate two threats', function (done) {

    var element = { attributes: { type: 'tm.Process' }};
    var threats;

    runs(function () {
        threatengine.generateForElement(element).then(function (data) {
            threats = data;
        });
        $rootScope.$apply();
        });

        waitsFor(function () {
            return typeof threats !== 'undefined';
    });

    runs(function () {
        expect(threats).not.toBeUndefined();
        expect(threats).toBeDefined();
        expect(threats.length).toEqual(20);
    });

});

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Angular JS服务中的单元测试承诺

来自分类Dev

Angular 服务中的单元测试 $q 承诺 - Karma、Jasmine

来自分类Dev

Angular 单元测试服务

来自分类Dev

单元测试 Angular 服务

来自分类Dev

Angular.js承诺在使用业力进行单元测试服务时不会解决

来自分类Dev

如何在Promise的承诺上使Node单元测试失败?

来自分类Dev

返回承诺Angularjs Jasmine的单元测试服务

来自分类Dev

AngularJS中的单元测试-模拟服务和承诺

来自分类Dev

返回承诺Angularjs Jasmine的单元测试服务

来自分类Dev

回报承诺的Jasmine单元测试角度服务无法解决

来自分类Dev

Angular服务的简单单元测试

来自分类Dev

Angular8服务单元测试

来自分类Dev

注入服务的 Angular 单元测试

来自分类Dev

单元测试失败

来自分类Dev

Angular2服务单元测试因TypeError失败:undefined不是对象

来自分类Dev

监视服务方法时,Jasmine单元测试失败

来自分类Dev

监视服务方法时,Jasmine单元测试失败

来自分类Dev

基于angularjs单元测试承诺的服务(SQlite数据库服务)

来自分类Dev

Umbraco单元测试失败

来自分类Dev

验证单元测试失败

来自分类Dev

“单元测试失败”的BeautifulSoup

来自分类Dev

Umbraco单元测试失败

来自分类Dev

Rails单元测试失败

来自分类Dev

Angular 单元测试在使用(提交)时失败

来自分类Dev

使用 rxjs switchmap 时,angular 5 单元测试失败

来自分类Dev

由于构造函数中的组件,Angular 单元测试失败。

来自分类Dev

带有@ContentChild 的 Angular 单元测试失败

来自分类Dev

AngularJS中的单元测试承诺

来自分类Dev

AngularJS单元测试解决承诺