gpt4 book ai didi

unit-testing - 如何在 Angular2 中监视服务调用

转载 作者:太空狗 更新时间:2023-10-29 16:52:25 25 4
gpt4 key购买 nike

按照在 Ari Lerner ng-book2 上找到的代码示例,并使用 Angular 2 beta 7,我试图模拟和监视对服务的调用失败。

这是使用该服务的主要组件:

user-list.component.ts

import {Component, OnInit} from 'angular2/core';
import {UserService} from './user.service';
import {IUser} from './user.model';

@Component({
selector: 'user-list',
providers: [UserService],
template: `
<div *ngFor="#user of users" class="user">
<span class="username">Username: {{ user.username }}</span><br>
<span class="email">Email: {{ user.email }}</span>
</div>
`
})
export class UserListComponent implements OnInit {
public users: IUser[];
private userService: UserService;

constructor(userService: UserService) {
this.userService = userService;
}

ngOnInit(): void {
this.userService.getAllUsers().subscribe(
(users: IUser[]) => {
this.users = users;
},
(error: any) => {
console.log(error);
}
);
}
}

这就是服务本身。

user.service.ts

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/Rx';
import {IUser} from './user.model';

@Injectable()
export class UserService {
private http: Http;
private baseUrl: string = 'http://jsonplaceholder.typicode.com/users';

constructor(http: Http) {
this.http = http;
}

public getAllUsers(): Observable<IUser[]> {
return this.http.get(this.baseUrl)
.map(res => res.json());
}
}

为了测试 UserListComponent,我尝试模拟 UserService 并使用以下代码监视其方法调用 getAllUser:

user-list.component.spec.ts

import {
describe,
expect,
it,
injectAsync,
TestComponentBuilder,
ComponentFixture,
setBaseTestProviders,
} from 'angular2/testing';

import {SpyObject} from 'angular2/testing_internal';

import {
TEST_BROWSER_PLATFORM_PROVIDERS,
TEST_BROWSER_APPLICATION_PROVIDERS
} from 'angular2/platform/testing/browser';

import {provide} from 'angular2/core';

import {UserListComponent} from './user-list.component';
import {UserService} from './user.service';

class SpyUserService extends SpyObject {
public getAllUsers: Function;
public fakeResponse: any = null;

constructor() {
super(UserService);
this.getAllUsers = this.spy('getAllUsers').andReturn(this);
}

public subscribe(callback) {
callback(this.fakeResponse);
}

public setResponse(data: any): void {
this.fakeResponse = data;
}
}

describe('When rendering the UserListComponent and mocking the UserService', () => {

setBaseTestProviders(TEST_BROWSER_PLATFORM_PROVIDERS, TEST_BROWSER_APPLICATION_PROVIDERS);

it('should show one mocked user', injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {

let spyUserService = new SpyUserService();
spyUserService.setResponse([{
username: 'ryan',
email: 'ryan@gmail.com'
}]);

return tcb
.overrideProviders(UserListComponent, [provide(UserService, {useValue: spyUserService})])
.createAsync(UserListComponent)
.then((fixture: ComponentFixture) => {
fixture.detectChanges();
expect(spyUserService.getAllUsers).toHaveBeenCalled();
});
}));

});

当使用 karma 运行测试时,我收到以下控制台错误:

Chrome 48.0.2564 (Mac OS X 10.11.3) ERROR
Uncaught TypeError: Cannot read property 'isSlow' of null
at /Users/david/apps/sandbox/angular2-testing-cookbook/src/tests.entry.ts:19430

有人知道为什么会抛出这个错误,或者知道模拟和监视服务以对 Angular 2 组件进行单元测试的正确方法吗?

最佳答案

我采用了一种稍微不同的方法,使用注入(inject)自身来通过 DI 获取服务实例。所以你的测试看起来像:

import {
describe,
expect,
it,
tick,
inject,
fakeAsync,
TestComponentBuilder,
ComponentFixture,
addProviders
} from 'angular2/testing';

import { Component, provide } from '@angular/core';

import {UserListComponent} from './user-list.component';

import {UserService} from './user.service';
import {MockUserService} from './user.service.mock';

describe('When loading the UserListComponent', () => {

beforeEach(() => addProviders([
{provide: UserService, useClass: MockUserService}
]));

it('should call the getAllUsers method from the UserService',
inject([TestComponentBuilder, UserService], fakeAsync((tcb: TestComponentBuilder, mockUserService: UserService) => {
spyOn(mockUserService, 'getAllUsers');

tcb
.createAsync(UserListComponent)
.then((fixture: ComponentFixture) => {
tick();
fixture.detectChanges();
expect(mockUserService.getAllUsers).toHaveBeenCalled();
});
}))
);

it('should show one mocked user',
inject([TestComponentBuilder, UserService], fakeAsync((tcb: TestComponentBuilder, mockUserService: UserService) => {
mockUserService.setResponse([{
username: 'ryan',
email: 'ryan@gmail.com'
}]);

tcb
.createAsync(UserListComponent)
.then((fixture: ComponentFixture) => {
tick();
fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('div:nth-child(1) .username')).toHaveText('Username: ryan');
expect(compiled.querySelector('div:nth-child(1) .email')).toHaveText('Email: ryan@gmail.com');
});
}))
);

});

为 Angular 4 编辑

最新docs使用组件的注入(inject)器有一种更简单的方法来获取服务:

  fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
const mockService = fixture.debugElement.injector.get(MyService);

为 Angular 5+ 编辑

  import { Component, Injector, Type } from '@angular/core';
...

fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
const mockService = fixture.debugElement.injector.get<MyService>(MyService as Type<MyService>);

关于unit-testing - 如何在 Angular2 中监视服务调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35733846/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com