在单元测试中永远不会调用间谍服务(茉莉角)

问题描述 投票:0回答:1

我试图理解为什么我的测试没有按预期进行。这是组件:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [HomeService]
})
export class AppComponent {
  title = 'testing-angular';

  constructor (private service: HomeService ) {}

  CallHomeService(): void {
    this.service.DoStuff();
  }
}

这里的服务:

@Injectable()
export class HomeService {

  constructor() { }

  DoStuff(): void {
    console.log('homeService has been called')
  }

}

我只想检查

DoStuff
是否被调用,所以我做了这个测试:

describe('AppComponent', () => {
  let fixture: ComponentFixture<AppComponent>;
  let appComponent: AppComponent;
  let homeServiceMock: jasmine.SpyObj<HomeService>; // Use jasmine.SpyObj type for mock

  beforeEach(() => {
    // Create a spy object for HomeService
    homeServiceMock = jasmine.createSpyObj('HomeService', ['DoStuff']);

    TestBed.configureTestingModule({
      declarations: [AppComponent],
      providers: [{provide: HomeService, useValue: homeServiceMock}] // Provide the spy object directly
    });

    fixture = TestBed.createComponent(AppComponent);
    appComponent = fixture.componentInstance;
  });

  it('should call DoStuff() when CallHomeService() is called', () => {
    // Call the CallHomeService() method of AppComponent
    appComponent.CallHomeService();

    // Expect that DoStuff() was called on the mock HomeService
    expect(homeServiceMock.DoStuff).toHaveBeenCalled(); // Use toHaveBeenCalled() matcher
  });
});

但我明白了

AppComponent should call DoStuff() when CallHomeService() is called FAILED
        Expected spy HomeService.DoStuff to have been called.
            at <Jasmine>
            at UserContext.apply (src/app/app.component.spec.ts:28:37)
            at _ZoneDelegate.invoke (node_modules/zone.js/fesm2015/zone.js:375:26)
            at ProxyZoneSpec.onInvoke (node_modules/zone.js/fesm2015/zone-testing.js:287:39)
            at _ZoneDelegate.invoke (node_modules/zone.js/fesm2015/zone.js:374:52)

所以我尝试使用 TestBed.overrideProvider 并且它起作用了:

import { TestBed, ComponentFixture } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { HomeService } from './service/home.service';

describe('AppComponent', () => {
  let fixture: ComponentFixture<AppComponent>;
  let appComponent: AppComponent;
  let homeService: jasmine.SpyObj<HomeService>; // Use jasmine.SpyObj type for mock

  beforeEach(() => {
    // Create a mock object for HomeService
    const homeServiceMock = jasmine.createSpyObj('HomeService', ['DoStuff']);

    TestBed.configureTestingModule({
      declarations: [AppComponent],
      providers: []
    });

    // Override the provider for HomeService with the mock
    TestBed.overrideProvider(HomeService, { useValue: homeServiceMock });

    fixture = TestBed.createComponent(AppComponent);
    appComponent = fixture.componentInstance;
  });

  it('should call DoStuff() when CallHomeService() is called', () => {
    // Call the CallHomeService() method of AppComponent
    appComponent.CallHomeService();

    // Expect that DoStuff() was called on the mock HomeService
    expect(homeService.DoStuff).toHaveBeenCalled();
  });
});

我看到 here 如果我在 ts 组件中使用

providers
它将覆盖我的间谍,但我仍然不明白为什么我的 useValue 被覆盖。不应该只在
providers
TestBed.configureTestingModule
提供mock服务,用
useValue
来调用mock服务吗?感谢您的帮助。

angular unit-testing jasmine testbed
1个回答
0
投票

由于您通过组件的

HomeService
数组向组件提供
providers
,因此该组件没有获得在模块级别创建的
HomeService
的实例——您用
useValue
替换的实例——它获得了自己的实例,单独的实例。

来自文档

Angular DI 具有分层注入系统,这意味着嵌套的注入器可以创建自己的服务实例。每当 Angular 创建一个组件的新实例,该实例具有在 @Component() 中指定的提供者时,它也会为该实例创建一个新的子注入器。

子模块和组件注入器相互独立,并创建自己独立的提供服务实例。

© www.soinside.com 2019 - 2024. All rights reserved.