Angular 2 rc5,使用注入的管道的单元测试问题 [英] Angular 2 rc5 , unit testing issue with pipes that use injection

查看:15
本文介绍了Angular 2 rc5,使用注入的管道的单元测试问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 angular2 rc 5,我编写了一个从 json 获取值的自定义管道.自定义管道:literal.pipe.ts 看起来像:

从 '@angular/core' 导入 {Pipe, PipeTransform, Inject};从'../service/message.service'导入{MessageService};@管道({名称:'字面串',纯:假})导出类 LiteralPipe 实现 PipeTransform{私信Bundle:any;私人要求:任何;构造函数(私有_messageService:MessageService){this._messageService = _messageService;this.messageBundle = {};}转换(值:字符串,参数:字符串 []):任何 {如果(!this.request){this.request = this._messageService.getBundle();this.request.subscribe((数据:任何)=>this.messageBundle = 数据);}如果(this.messageBundle[值])返回 this.messageBundle[值];否则如果(参数 [0])返回参数;别的return "字符串不可用.请包含在 bundle.json 中";}}

MessageService.ts:

从@angular/core"导入 {Injectable}从'@angular/http'导入{Http};导入'rxjs/Rx'@Injectable()导出类 MessageService{http:任何;构造函数(http:http){这个.http = http;}获取捆绑(){返回 this.http.get('../src/bundle.json').map((res:any) => res.json());}}

Bundle.json 的键值对为

<代码>{"Home.title": "登录","DashBoard.Title": "仪表板","CheckOutGiftCard.Title": "礼品卡结账"}

我正在使用 liteServer 运行我的单元测试.我的 unitTests.html:

<meta http-equiv="content-type" content="text/html;charset=utf-8"><title>Ng 应用单元测试</title><link rel="stylesheet" href="../node_modules/jasmine-core/lib/jasmine-core/jasmine.css"><script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script><script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script><script src="../node_modules/jasmine-core/lib/jasmine-core/boot.js"></script><script src="node_modules/zone.js/dist/zone.js"></script><script src="node_modules/reflect-metadata/Reflect.js"></script><script src="node_modules/systemjs/dist/system.src.js"></script><script src="systemjs.config.js"></script></头><身体><!-- 单元测试第 1 章:生命证明.--><脚本>it('true is true', function(){ expect(true).toEqual(true); });</脚本><脚本>//#2.配置 systemjs 以使用 .js 扩展名//用于从 app 文件夹导入System.config({defaultJSExtensions:true});//#3.加载并配置 TestComponentBuilder.//#2.显式导入规范文件承诺.所有([System.import('app/literal.pipe.spec')])//#3.等待所有导入加载...//然后重新执行 `window.onload`//触发 Jasmine 测试运行器启动//或者解释出了什么问题.//System.import('app/literal.pipe.spec').then(window.onload).catch(console.error.bind(console));</脚本></身体></html>

literal.pipe.spec.ts如下:

import { By } from '@angular/platform-b​​rowser';从'@angular/core'导入{提供};从@angular/core"导入 { ViewMetadata };从'../pipe/literal.pipe'导入{LiteralPipe};从'../service/message.service'导入{MessageService};从'@angular/http'导入{Http};从'@angular/core/testing'导入{TestBed};//import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-b​​rowser-dynamic/testing';//TestBed.initTestEnvironment(//BrowserDynamicTestingModule,//platformBrowserDynamicTesting()//);让管道:LiteralPipe;让 msgService: MessageService;//////// 眼镜 /////////////描述('LiteralPipe', () => {beforeEach(()=>{[addProviders([MessageService]) ]});TestBed.configureTestingModule({声明:[消息服务],提供者:[{provide:MessageService, useClass:MessageService}],导入:[MessageService,Http]});it('可以获得一个实例', inject([MessageService], (msgService: MessageService) => {//使用msgService作为服务实例创建管道实例.管道 = 新的 LiteralPipe(msgService);}));it('将Home.title"转换为Login"', () => {expect(pipe.transform('Home.title', null)).toEqual('Login');});});

看起来我在规范文件的某个地方出错了,因为当我运行 npm test 并查看在浏览器中打开的 unitTests 时,我收到以下异常:

LiteralPipe 可以获取实例TypeError:无法读取 null 的属性注入器"TypeError:无法读取 null 的属性注入器"在 TestBed._createCompilerAndModule (http://localhost:3000/node_modules/@angular/core/testing/test_bed.js:246:44)在 TestBed._initIfNeeded (http://localhost:3000/node_modules/@angular/core/testing/test_bed.js:213:39)在 TestBed.execute (http://localhost:3000/node_modules/@angular/core/testing/test_bed.js:274:14)在 Object.eval (http://localhost:3000/node_modules/@angular/core/testing/test_bed.js:404:45)在尝试同步(http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1886:24)在 QueueRunner.run (http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1874:9)在 QueueRunner.execute (http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1859:10)在 Spec.queueRunnerFactory (http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:697:35)在 Spec.execute (http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:359:10)在 Object.fn (http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2479:37)LiteralPipe 将Home.title"转换为Login"TypeError:无法读取未定义的属性转换"TypeError:无法读取未定义的属性转换"在 Object.eval (http://localhost:3000/app/literal.pipe.spec.js:30:20)在尝试同步(http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1886:24)

我应该改变什么来完成这项工作.

解决方案

这里的问题是你错误地使用了TeseBed.下面的示例是您的 literal.pipe.spec.ts 文件的修改版本.

主要是你必须在初始化之前重置测试环境.

<上一页>TestBed.resetTestEnvironment();

一旦环境被重置,configureTestingModule 必须被配置:

<上一页>测试台.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()).configureTestingModule({providers: [MessageService],imports: [HttpModule]});

import {By} from '@angular/platform-b​​rowser';从@angular/core"导入{provide};从'@angular/core'导入{ViewMetadata};从'./pipe/literal.pipe'导入{LiteralPipe};从'../services/message.service'导入{MessageService};从'@angular/http'导入{Http};从'@angular/core/testing'导入{inject, TestBed};从@angular/platform-b​​rowser-dynamic/testing"导入 {BrowserDynamicTestingModule, platformBrowserDynamicTesting};从@angular/http"导入 {HttpModule};让管道:LiteralPipe;让 msgService: MessageService;//////// 眼镜 /////////////描述('LiteralPipe', () => {beforeEach(() => {//必须在初始化之前重置测试环境.TestBed.resetTestEnvironment();测试台.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()).configureTestingModule({声明:[],提供者:[消息服务],进口:[Http模块]});});it('将Home.title"转换为Login"', inject([MessageService], (msgService: MessageService) => {让 pipe = new LiteralPipe(msgService);expect(pipe.transform('Home.title', null)).toEqual('Login');}));});


您的管道实现本身也存在问题.在尝试从中获取值之前,您应该检查 args 变量是否不为空.

literal.pipe.ts

<上一页>如果(this.messageBundle[值])返回 this.messageBundle[值];否则 if(args != null && args[0])返回参数;别的return "字符串不可用.请包含在 bundle.json 中";

I am using angular2 rc 5, I have written a custom pipe that fetches value from a json. The custom pipe : literal.pipe.ts looks like :

import {Pipe, PipeTransform, Inject} from '@angular/core';
import {MessageService} from '../service/message.service';

@Pipe({
  name: 'literalString',
  pure: false
})
export class LiteralPipe  implements PipeTransform{

private messageBundle:any;
private request:any;

    constructor(private _messageService: MessageService){
        this._messageService = _messageService;
        this.messageBundle = {};
    }

    transform(value:string, args:string[]):any {
        if(!this.request){
            this.request = this._messageService.getBundle();
            this.request.subscribe(
                (data:any) => this.messageBundle = data
             );
        }

         if(this.messageBundle[value])
             return this.messageBundle[value];
        else if(args[0])
            return args; 
         else
            return "String not available. Pls include in bundle.json";
    }
}

MessageService.ts :

import {Injectable} from "@angular/core"
import {Http} from '@angular/http';
import 'rxjs/Rx'

@Injectable()
export class MessageService{
    http:any;
    constructor(http: Http){
        this.http = http;
    }
    getBundle (){
        return this.http.get('../src/bundle.json').map((res:any) => res.json());
    }
}

Bundle.json has key value pairs as

{
            "Home.title": "Login",
            "DashBoard.Title": "Dashboard",
            "CheckOutGiftCard.Title": "GIFT CARD CHECKOUT"
}

I am running my unit tests using liteServer. My unitTests.html:

<meta http-equiv="content-type" content="text/html;charset=utf-8">
  <title>Ng App Unit Tests</title>
  <link rel="stylesheet" href="../node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
  <script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script>
  <script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
  <script src="../node_modules/jasmine-core/lib/jasmine-core/boot.js"></script>
  <script src="node_modules/zone.js/dist/zone.js"></script>

  <script src="node_modules/reflect-metadata/Reflect.js"></script>

  <script src="node_modules/systemjs/dist/system.src.js"></script>

  <script src="systemjs.config.js"></script>
</head>
<body>
  <!-- Unit Testing Chapter #1: Proof of life.  -->
  <script>
    it('true is true', function(){ expect(true).toEqual(true); });
  </script>
  <script>
    // #2. Configure systemjs to use the .js extension
    //     for imports from the app folder
    System.config({defaultJSExtensions:true});
    // #3. Load and configure the TestComponentBuilder.
    // #2. Import the spec files explicitly
    Promise.all([
      System.import('app/literal.pipe.spec')
    ])
    // #3. wait for all imports to load ...
    //     then re-execute `window.onload` which
    //     triggers the Jasmine test-runner start
    //     or explain what went wrong.
    //System.import('app/literal.pipe.spec')
    .then(window.onload)
    .catch(console.error.bind(console));
  </script>
</body>
</html>

literal.pipe.spec.ts is as follows:

import { By }             from '@angular/platform-browser';
import { provide }        from '@angular/core';
import { ViewMetadata }   from '@angular/core';
import {LiteralPipe} from '../pipe/literal.pipe';
import {MessageService} from '../service/message.service';
import {Http} from '@angular/http';
import { TestBed } from '@angular/core/testing';
//import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing';

// TestBed.initTestEnvironment(
//     BrowserDynamicTestingModule,
//     platformBrowserDynamicTesting()
//     );


  let pipe: LiteralPipe;
  let msgService: MessageService;
////////  SPECS  /////////////
describe('LiteralPipe', () => {
    beforeEach(()=>{
    [addProviders([MessageService]) ]
  });

 TestBed.configureTestingModule({
   declarations:[MessageService],
    providers: [{provide:MessageService, useClass:MessageService }  ],
    imports: [MessageService, Http]
  });
  it('can get an instance', inject([MessageService], (msgService: MessageService) => {
    //create instance of pipe using msgService as the instance of service. 
    pipe = new LiteralPipe(msgService);
  }));
  it('transforms "Home.title" to "Login"', () => {
    expect(pipe.transform('Home.title', null)).toEqual('Login');
  });
});

It looks like I am going wrong somewhere in the spec file as when I run npm test and view the unitTests that opens in the browser I get the following exception:

LiteralPipe can get an instance
TypeError: Cannot read property 'injector' of null
TypeError: Cannot read property 'injector' of null
    at TestBed._createCompilerAndModule (http://localhost:3000/node_modules/@angular/core/testing/test_bed.js:246:44)
    at TestBed._initIfNeeded (http://localhost:3000/node_modules/@angular/core/testing/test_bed.js:213:39)
    at TestBed.execute (http://localhost:3000/node_modules/@angular/core/testing/test_bed.js:274:14)
    at Object.eval (http://localhost:3000/node_modules/@angular/core/testing/test_bed.js:404:45)
    at attemptSync (http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1886:24)
    at QueueRunner.run (http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1874:9)
    at QueueRunner.execute (http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1859:10)
    at Spec.queueRunnerFactory (http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:697:35)
    at Spec.execute (http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:359:10)
    at Object.fn (http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2479:37)
LiteralPipe transforms "Home.title" to "Login"
TypeError: Cannot read property 'transform' of undefined
TypeError: Cannot read property 'transform' of undefined
    at Object.eval (http://localhost:3000/app/literal.pipe.spec.js:30:20)
    at attemptSync (http://localhost:3000/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1886:24)

What should I change to make this work.

解决方案

The problem here is that you are using TeseBed incorrectly. The example below is modified version of your literal.pipe.spec.ts file.

Main bit is that you have to reset test environment before initialising it.


    TestBed.resetTestEnvironment();

Once environment is reset the the configureTestingModule has to be configured:


    TestBed
    .initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting())
    .configureTestingModule({providers: [MessageService],imports: [HttpModule]});

import {By}             from '@angular/platform-browser';
import {provide}        from '@angular/core';
import {ViewMetadata}   from '@angular/core';
import {LiteralPipe} from './pipe/literal.pipe';
import {MessageService} from '../services/message.service';
import {Http} from '@angular/http';
import {inject, TestBed} from '@angular/core/testing';
import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from "@angular/platform-browser-dynamic/testing";
import {HttpModule} from '@angular/http';

let pipe: LiteralPipe;
let msgService: MessageService;
////////  SPECS  /////////////
describe('LiteralPipe', () => {
  beforeEach(() => {
    // Must reset the test environment before initializing it.
    TestBed.resetTestEnvironment();

    TestBed
      .initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting())
      .configureTestingModule({
        declarations: [],
        providers: [
          MessageService
        ],
        imports: [
          HttpModule
        ]
      });
  });
  
  it('transforms "Home.title" to "Login"', inject([MessageService], (msgService: MessageService) => {
    let pipe = new LiteralPipe(msgService);
    expect(pipe.transform('Home.title', null)).toEqual('Login');
  })
  );
});


Also there is a problem with your pipe implementation itself. You should check if args variable is not null before trying to get value from it.

literal.pipe.ts



    if(this.messageBundle[value])
          return this.messageBundle[value];
        else if(args != null && args[0])
          return args;
        else
          return "String not available. Pls include in bundle.json";

这篇关于Angular 2 rc5,使用注入的管道的单元测试问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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