【问题标题】:Angular2: Testing component with dependency injectionAngular2:使用依赖注入测试组件
【发布时间】:2016-04-12 16:49:06
【问题描述】:

我有一个简单但复杂(目前)的组件:它只是一个登录表单 所以我不会粘贴 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);
        });
    }));
});

还有我的翻译服务:

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 浏览器中......

【问题讨论】:

  • 提供一个关于你想要测试的更具体的例子怎么样。你试过什么?问题出在哪里?
  • 感谢您的关注。所以我在描述中添加了我的尝试:正如我之前提到的,我需要开始测试这个组件,现在假设我只需要测试这个登录表单的翻译标签是否存在并且正确。为此,我认为我需要注入 TranslationService(请参阅我的依赖于 ng2-translate 的翻译服务)。显然它不起作用,因为我不知道该怎么做。谢谢!
  • 我更进一步:我通过将一些所需的库添加到 karma.conf.js 来修复了没有一些所需库的错误。现在我可以去处理实际的测试了。下一步:修复提供程序!
  • @ng-flo 你到底做了什么来修复它,因为我看到了同样的问题。

标签: angular karma-jasmine


【解决方案1】:

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

一些可能有用的链接

test/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 {
}

【讨论】:

  • 我试过了,我得到了这个错误:debug.html:38 失败:没有 ApplicationRef 的提供者! (LoginComponent -> Router -> RouteRegistry -> Token RouterPrimaryComponent -> ApplicationRef) 错误:DI 异常
  • 抱歉,无法复制。
猜你喜欢
  • 2018-03-03
  • 2017-09-17
  • 2017-07-23
  • 2017-02-07
  • 1970-01-01
  • 2017-02-24
  • 1970-01-01
  • 1970-01-01
  • 2018-01-27
相关资源
最近更新 更多