Угловой 2 RC5, проблема модульного тестирования с трубами, которые используют впрыск

Я использую Angular2 RC 5, я написал пользовательский канал, который выбирает значение из JSON. Пользовательский канал: literal.pipe.ts выглядит так:

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 имеет пары ключ-значение в виде

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

Я запускаю свои модульные тесты, используя liteServer. Мой 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 выглядит следующим образом:

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');
  });
});

Похоже, что я ошибаюсь где-то в файле спецификации, так как при запуске npm test и просмотре unitTests, который открывается в браузере, я получаю следующее исключение:

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)

Что я должен изменить, чтобы сделать эту работу.

1 ответ

Проблема в том, что вы используете TeseBed неправильно. Пример ниже представляет собой модифицированную версию вашего файла literal.pipe.spec.ts.

Главный бит в том, что вы должны сбросить тестовую среду перед ее инициализацией.

    TestBed.resetTestEnvironment ();

После сброса среды необходимо настроить configureTestingModule:

    TestBed.initTestEnvironment (BrowserDynamicTestingModule, platformBrowserDynamicTesting ()).configureTestingModule ({provider: [MessageService], импорт: [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 не равна нулю, прежде чем пытаться получить значение из нее.

literal.pipe.ts



    если (this.messageBundle[значение])
          вернуть this.messageBundle [значение];
        иначе if(args!= null && args[0])
          вернуть аргументы;
        еще
          return "Строка не доступна. Просьба включить в bundle.json";

Другие вопросы по тегам