【问题标题】:Injected stub service in angular compontent returns wrong value角度组件中注入的存根服务返回错误值
【发布时间】:2016-12-12 10:46:57
【问题描述】:

我尝试为使用服务的 Angular 组件编写测试。 我用 true 初始化了我的 userServiceStub 属性 isLoggedIn,但是当我运行测试组件时,UserService 属性为 false。 我尝试删除 Injectable() 装饰器并将匿名对象更改为 UserService。

测试

import { async, ComponentFixture, ComponentFixtureAutoDetect, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { WelcomeComponent } from './welcome.component';
import { UserService, User } from './model';

class UserServiceMock{
    isLoggedIn: boolean = true;
    user: User = {name: 'Mock user'};
}

describe('Welcome component tests', () =>{

    let component:      WelcomeComponent;
    let fixture:        ComponentFixture<WelcomeComponent>;
    let debugElment:    DebugElement;
    let htmlElement:    HTMLElement;
    let userService:    UserService;

    let userServiceStub: {
        isLoggedIn: boolean;
        user: { name: string }
    };

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [WelcomeComponent],
        })
        .overrideComponent(WelcomeComponent, {
            set: {
                providers: [
                    {provide: UserService, useClass: UserServiceMock}
                ]
            }
        })
        .compileComponents()
        .then(() =>{
            fixture = TestBed.createComponent(WelcomeComponent);

            component = fixture.componentInstance;

            userService = TestBed.get(UserService);
            console.log(userService);
            debugElment = fixture.debugElement.query(By.css('.welcome'));
            htmlElement = debugElment.nativeElement;
        });
    });

    it('stub object and injected UserService should not be the same', () =>{
        expect(userServiceStub === userService).toBe(false);
    });

    it('changing the stub object has no effect on the injected service', () =>{
        userServiceStub.isLoggedIn = false;
        expect(userService.isLoggedIn).toBe(true);
    });

    it('should welcome user', () => {
        fixture.detectChanges();
        const content = htmlElement.textContent;
        expect(content).toContain('Welcome');
    })
})

欢迎组件

import { Component, OnInit } from '@angular/core';
import { UserService }       from './model';

@Component({
  selector: 'app-welcome',
  template: '<h3 class="welcome" ><i>{{welcome}}</i></h3>',
  providers: [UserService]
})
export class WelcomeComponent  implements OnInit {
  welcome: string = '-- not initialized yet --';
  constructor(private userService: UserService) { }

  ngOnInit(): void {
    this.welcome = this.userService.isLoggedIn ?
      'Welcome, ' + this.userService.user.name :
      'Please log in.';
  }
}

用户服务

import { Injectable } from '@angular/core';

@Injectable()
export class UserService {
    isLoggedIn: boolean;
    user: User;

}

export class User{
    name: string;
}

测试结果失败 link

我的问题是:如何正确注入服务?

【问题讨论】:

  • 您是否尝试将 providers: [UserService] 放入 WelcomeComponent 的 @Component({}) 中?你也可以看看这个stackoverflow.com/questions/39894179/…
  • 我在 WelcomeComponent 中添加了这一行 ` providers: [UserService] `,并将 TestBed.overrideComponent 与我的 UserService 一起使用。所有测试开始失败,因为 userService 未定义。
  • 尝试在 beforeEach 中添加异步。然后它会等到你的变量被初始化

标签: javascript angular jasmine


【解决方案1】:

1) 如果使用 compileComponent(),则必须使用 asyncfakeAsync

2) 当您在组件内提供服务时,您应该使用:

fixture.debugElement.injector.get(UserService);

获取注入服务

3) 您不能更改未定义对象的属性:

let userServiceStub: {
    isLoggedIn: boolean;
    user: { name: string }
};

userServiceStub.isLoggedIn = false;

userServiceStub 未定义。而且我不明白为什么 userServicesSub 在这里,如果你不使用它作为 useValue 在这里描述https://angular.io/docs/ts/latest/guide/testing.html#!#final-setup-and-tests

所以你的测试可能看起来像:

describe('Welcome component tests', () =>{
    let component:      WelcomeComponent;
    let fixture:        ComponentFixture<WelcomeComponent>;
    let debugElment:    DebugElement;
    let htmlElement:    HTMLElement;
    let userService:    UserService;

    let userServiceStub: {
        isLoggedIn: boolean;
        user: { name: string }
    } = { 
      isLoggedIn: true, 
      user: { name: 'Stub user'}
    };

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [WelcomeComponent],
        })
        .overrideComponent(WelcomeComponent, {
            set: {
                providers: [
                    {provide: UserService, useClass: UserServiceMock}
                ]
            }
        })
        .compileComponents()
        .then(() =>{
            fixture = TestBed.createComponent(WelcomeComponent);

            component = fixture.componentInstance;

            //userService = TestBed.get(UserService);

            userService = fixture.debugElement.injector.get(UserService);

            console.log(userService);
            debugElment = fixture.debugElement.query(By.css('.welcome'));
            htmlElement = debugElment.nativeElement;
        });
    }));

    it('stub object and injected UserService should not be the same', () =>{
        expect(userServiceStub === userService).toBe(false);
    });

    it('changing the stub object has no effect on the injected service', () =>{
        userServiceStub.isLoggedIn = false;
        expect(userService.isLoggedIn).toBe(true);
    });

    it('should welcome user', () => {
        fixture.detectChanges();
        const content = htmlElement.textContent;
        expect(content).toContain('Welcome');
    })
})

Live Example

【讨论】:

  • 谢谢!在第一个版本中,我使用了 userServicesSub,但后来我尝试创建模拟并忘记删除此存根。
猜你喜欢
  • 2019-01-11
  • 1970-01-01
  • 1970-01-01
  • 2021-05-19
  • 2019-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-27
相关资源
最近更新 更多