Angular2:使用依赖注入测试组件

时间:2016-04-12 16:49:07

标签: angular karma-jasmine

我有一个简单但复杂的(现在)组件:它只是一个登录表单 所以我不会粘贴html。看起来像这样:

login.component.ts

@Component({
    selector: 'login',
    providers: [ModuleLoaderService, LoginService],
    templateUrl: 'login.component.html',
    directives: [CORE_DIRECTIVES, RouterLink],
    pipes: [TranslationPipe]
})

export class LoginComponent {

//... some stuff
    constructor(public router: Router, public http: Http, private _translation: TranslationService,
                private _loginService: LoginService, private _moduleLoaderService: ModuleLoaderService) {
                    // do stuff using translation, etc
                }

                ....
 ngOnInit() {
`....bla bla
}

这是我开始尝试的测试,我认为完全是这样:

describe('Login form', () => {
    beforeEachProviders(() => [
                                provide(Http, {useFactory: (backend: ConnectionBackend, defaultOptions: BaseRequestOptions) => {
                                    return new Http(backend, defaultOptions);
                                }, deps: [MockBackend, BaseRequestOptions]}),
                                TranslationService,
                                LoginService
    ]);

    it('should check translated labels', injectAsync([TestComponentBuilder], (tcb) => {
        return tcb.createAsync(MockLoginComponent).then((fixture) => {
            fixture.detectChanges();
            let compiled = fixture.debugElement.nativeElement;
            expect(true).toBe(true);
        });
    }));
});

和我的TranslationService:

import { Injectable } from 'angular2/core';
import { TranslateService } from 'ng2-translate';

@Injectable()
export class TranslationService {

    constructor( private _translate: TranslateService ) {
        //
     }

错误:

无法加载资源:服务器响应状态为404(未找到):http://localhost:9876/ng2-translate

我想开始为这个组件编写测试。我认为第一个测试是一个好的开始:测试翻译的标签是正确的(或其他任何简单的标签)。我不知道如何注入或模拟所有这些构造函数参数。任何提示真的很赞赏。

更新: 所以我现在忽略了组件依赖,我实际上可以获得用于测试的组件:

describe('Login form', () => {
    beforeEachProviders(() => [
        HTTP_PROVIDERS,
        provide(XHRBackend, { useClass: MockBackend }),
        provide(Router, { useClass: MockRouter }),
        TranslateService,
        TranslationService,
        LoginService,
        provide(TranslateLoader, {
            useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'),
            deps: [Http]
        }),
        TranslateService,
        ModuleLoaderService
    ]);

    it('should pre-populate username and pass from localStorage', injectAsync([TestComponentBuilder], (tcb) => {
        return tcb.createAsync(LoginComponent).then((fixture) => {
            fixture.detectChanges();
            let compiled = fixture.debugElement.nativeElement;
            localStorage.setItem('username', 'storedUsername');           
            expect(compiled.querySelector('input .ng-untouched')).toHaveText('storedUsername');
        });
    }));

css选择器似乎无法正常工作,翻译的标签也不会在Karma浏览器中显示......

1 个答案:

答案 0 :(得分:0)

这可能会有所帮助。我不是自己使用TS(只有Dart),但它运行测试没有错误(实际上没有测试任何东西)。

一些可能有用的链接

<强>测试/ some.spec.ts

import {setBaseTestProviders} from 'angular2/testing';
import {
    TEST_BROWSER_PLATFORM_PROVIDERS,
    TEST_BROWSER_APPLICATION_PROVIDERS
} from 'angular2/platform/testing/browser';
import {Http, ConnectionBackend, BaseRequestOptions} from 'angular2/http';
import {ROUTER_PROVIDERS, ROUTER_PRIMARY_COMPONENT} from 'angular2/router';
import {
    //AsyncTestCompleter,
    TestComponentBuilder,
    beforeEachProviders,
    beforeEach,
    describe,
    // el,
    expect,
    inject,
    injectAsync,
    it,
} from 'angular2/testing';
import {Component, provide, ElementRef} from 'angular2/core';
import {LoginComponent, TranslationService} from '../src/app';
import {MockBackend} from "angular2/src/http/backends/mock_backend";

setBaseTestProviders(TEST_BROWSER_PLATFORM_PROVIDERS,
    TEST_BROWSER_APPLICATION_PROVIDERS);

describe('Login form', () => {
  beforeEachProviders(() => [provide(ROUTER_PRIMARY_COMPONENT, {useClass: LoginComponent}), TestComponentBuilder, ROUTER_PROVIDERS,
    provide(Http, {
      useFactory: (backend:ConnectionBackend, defaultOptions:BaseRequestOptions) => {
        return new Http(backend, defaultOptions);
      }, deps: [MockBackend, BaseRequestOptions]
    }),
    TranslationService,
  ]);

  it('should check translated labels', injectAsync([TestComponentBuilder], (tcb) => {
    return tcb.createAsync(LoginComponent).then((fixture) => {
      fixture.detectChanges();
      let compiled = fixture.debugElement.nativeElement;
      console.debug(compiled);
      expect(true).toBe(true);
    });
  }));
});

<强>的test.html

<!DOCTYPE html>
<html>

<head>
    <title>angular2 playground</title>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine-html.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/boot.js"></script>


    <link rel="stylesheet" href="style.css"/>
    <script src="https://code.angularjs.org/2.0.0-beta.15/angular2-polyfills.js"></script>
    <script src="https://code.angularjs.org/tools/system.js"></script>
    <script src="https://code.angularjs.org/tools/typescript.js"></script>
    <script src="config.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.15/Rx.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.15/angular2.dev.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.15/router.dev.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.15/http.dev.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.15/testing.dev.js"></script>
    <script>

        Promise.all([
          System.import('test/some.spec.ts')
        ])
        .then(window.onload)
                .catch(console.error.bind(console));
    </script>
</head>
<body>
</body>
</html>

<强>的src / app.ts

import {EventEmitter, HostListener, Component, Directive, Output} from 'angular2/core';
import {Http} from 'angular2/http';
import {RouterLink, Router, RouteConfig, RouterOutlet} from 'angular2/router';


export class TranslationService {
}

@Component({
  selector: 'home-cmp',
  template: '<div>home</div>'
})
class HomeComponent {
}

@Component({
  selector: 'login',
  providers: [TranslationService],
  template: '<div>login</div>',
})
export class LoginComponent {
  constructor(private _translation:TranslationService) {
    // do stuff using translation, etc
  }
}

@Component({
  directives: [RouterLink, RouterOutlet],
  selector: 'my-app',
  template: `
<a [routerLink]="['/Home']">Home</a>
<a [routerLink]="['/Login']">Login</a>
<router-outlet></router-outlet>`,
})
@RouteConfig([
  {path: '/home', component: HomeComponent, name: 'Home', useAsDefault: true},
  {path: '/login', component: LoginComponent, name: 'Login'},
])
export class App {
}