问题描述
我正在使用angular2 rc 5,我编写了一个从json获取值的自定义管道。自定义管道:literal.pipe.ts看起来像:
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:
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的键值对为
Bundle.json has key value pairs as
{
"Home.title": "Login",
"DashBoard.Title": "Dashboard",
"CheckOutGiftCard.Title": "GIFT CARD CHECKOUT"
}
I我正在使用liteServer运行我的单元测试。我的unitTests.html:
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如下:
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');
});
});
看起来我在spec文件的某处出错了,就像我运行npm test并查看在浏览器中打开的unitTests我得到以下异常:
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.
推荐答案
这里的问题是您使用的TeseBed不正确。下面的示例是literal.pipe.spec.ts文件的修改版本。
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();
重置环境后,必须配置configureTestingModule:
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');
})
);
});
此外,您的管道实施本身也存在问题。在尝试从中获取值之前,您应该检查args变量是否为空。
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,使用注射管道的单元测试问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!