Angular 2 rc5 , unit testing issue with pipes that use injection

给你一囗甜甜゛ 提交于 2019-12-01 07:35:03

问题


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.


回答1:


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";



来源:https://stackoverflow.com/questions/39018997/angular-2-rc5-unit-testing-issue-with-pipes-that-use-injection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!