角度组件中的注入存根服务返回错误值

时间:2016-12-12 10:46:58

标签: javascript angular jasmine

我尝试为使用服务的角度组件编写测试。 我用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

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

1 个答案:

答案 0 :(得分: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