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

查看:75
本文介绍了用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!')
    })
})

玩笑运行时,该指令似乎尚未链接/编译/任何内容

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 变量相同.

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)的调用不正确.

相反,您需要使用 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天全站免登陆