使用 Jest 对 AngularJS 指令进行单元测试 [英] Unit testing AngularJS Directives with Jest

查看:28
本文介绍了使用 Jest 对 AngularJS 指令进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我觉得我在这个极其简化的角度指令单元测试中遗漏了一些至关重要的东西:

I feel I am missing something crucial in this extremely simplified angular directive unit test:

import * as angular from 'angular'
import 'angular-mocks'

const app = angular.module('my-app', [])

app.directive('myDirective', () => ({
    template: 'this does not work either',
    link: (scope, element) => { // have also tried compile fn
        console.log('This does not log')
        element.html('Hi!')
    }
}))

describe('myDirective', () => {
    var element, scope

    beforeEach(app)

    beforeEach(inject(($rootScope, $compile) => {
        scope = $rootScope.$new()
        element = $compile('<my-directive />')(scope)
        scope.$digest()
    }))

    it('should actually do something', () => {
        expect(element.html()).toEqual('Hi!')
    })
})

当 jest 运行时,指令似乎没有被链接/编译/无论如何

When jest runs it appears the directive has not been linked/compiled/whatever

 FAIL  test/HtmlToPlaintextDirective.spec.js
  ● myDirective › should actually do something

    expect(received).toEqual(expected)

    Expected value to equal:
      "Hi!"
    Received:
      ""

推荐答案

更新答案:

您是对的,在单个文件中导入所有内容时,事情不会按预期工作.

You're right things don't work as expected when importing everything in a single file.

深入研究您似乎遇到了 Babel/Jest 为支持依赖于全局变量(如 AngularJS)的浏览器脚本所做的一些魔法.

Digging into things it looks like you're running into some magic that Babel/Jest does to support browser scripts that rely on globals (like AngularJS).

发生的情况是您的模块的 angular 变量与 angular-mocks 可见的全局 angular 变量相同.

What's happening is that your module's angular variable is not the same as the global angular variable that is visible to angular-mocks.

您可以通过在其中一个测试的顶部运行来检查这一点:

You can check this by running this at the top of one of your tests:

import * as angular from 'angular'
import 'angular-mocks'

console.log(angular === window.angular); // `false` in Jest!

console.log(angular.mock); // undefined
console.log(window.angular.mock); // `{...}` defined

要解决此问题,您只需在测试中使用全局 angular 变量即可.

To work around this you just need to use the global angular variable in your tests.

src/__test__/all-in-one.test.js:

import "angular";
import "angular-mocks";

/*
Work around Jest's window/global mock magic.

Use the global version of `angular` that has been augmented by angular-mocks.
*/
var angular = window.angular;


export var app = angular.module('app', []);

app.directive('myDirective', () => ({
    link: (scope, element) => {
        console.log('This does log');
        scope.content = 'Hi!';
    },
    template: 'content: {{content}}'
}));


describe('myDirective', function(){
    var element;
    var scope;

    beforeEach(function(){
        angular.mock.module(app.name);
    });

    it('should do something', function(){
        inject(function(
            $rootScope,
            $compile
        ){
            scope = $rootScope.$new();
            element = $compile('<my-directive></my-directive>')(scope);
            scope.$digest();
        });

        expect(element.html()).toEqual('content: Hi!');
    });
});

<小时>

原始答案:(这是因为我在测试中不小心使用了全局版本的 angular.)


Original answer: (This worked because I was accidentally using the global version of angular inside my test.)

测试中的 Angular 模块未在您的测试中正确初始化.

The Angular module under test isn't being initialised correctly in your tests.

您对 beforeEach(app) 的调用不正确.

Your call to beforeEach(app) isn't correct.

相反,您需要使用 angular.mock.module("moduleName") 来初始化您的模块.

Instead you need to use angular.mock.module("moduleName") to initialise your module.

describe('myDirective', () => {
    var element, scope

    // You need to pass the module name to `angular.mock.module()`
    beforeEach(function(){
        angular.mock.module(app.name);
    });


    // Then you can set up and run your tests as normal:
    beforeEach(inject(($rootScope, $compile) => {
        scope = $rootScope.$new()
        element = $compile('<my-directive></my-directive>')(scope)
        scope.$digest()
    }))

    it('should actually do something', () => {
        expect(element.html()).toEqual('Hi!')
    })
});

然后您的测试按我的预期工作:

And then your test works as expected for me:

 PASS  src\__test__app.test.js
  myDirective
    √ should do something (46ms)

<小时>

作为参考,这里是完整的应用程序和测试:


For reference, here is the full app and test:

src/app/app.module.js:

import * as angular from 'angular'

export var app = angular.module('app', []);

app.directive('myDirective', () => ({
    link: (scope, element) => {
        console.log('This does log');
        scope.content = 'Hi!';
    },
    template: 'content: {{content}}'
}))

src/__test__/app.test.js:

import {app} from "../app/app.module";
import "angular-mocks";

describe('myDirective', function(){
    var element;
    var scope;

    beforeEach(function(){
        angular.mock.module(app.name);
    });

    beforeEach(inject(function(
        $rootScope,
        $compile
    ){
        scope = $rootScope.$new();
        element = $compile('<my-directive></my-directive>')(scope);
        scope.$digest();
    }));

    it('should do something', function(){
        expect(element.html()).toEqual('content: Hi!');
    });
});

这篇关于使用 Jest 对 AngularJS 指令进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆