【问题标题】:How to mock service function in Angular component for unit test如何在 Angular 组件中模拟服务功能以进行单元测试
【发布时间】:2020-02-08 09:29:41
【问题描述】:

我正在为 Angular 应用程序编写单元测试,我正在测试服务函数是否返回值。

component.spec.ts

import {TopToolBarService} from '../../top-toolbar/top-toolbar.service';

beforeEach(async(() => {
   TestBed.configureTestingModule ({
   declarations: [ UsersListComponent],
   providers: [TopToolBarService],//tried mocking service here,still test failed
   schemas:[CUSTOM_ELEMENTS_SCHEMA]
 })
  .compileComponents();
}));



beforeEach(() => {
    fixture = TestBed.createComponent(UserListComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });



  it('should return data from service function', async(() => {
    let mockTopToolBarService: jasmine.SpyObj<TopToolBarService>;
    mockTopToolBarService = jasmine.createSpyObj('TopToolBarService', ['getCustomer']);
    mockTopToolBarService.getCustomer.and.returnValue("king");
    fixture.detectChanges();
    expect(component.bDefine).toBe(true); //fails
  }))

component.ts

bDefine = false;
ngOnInit() {
 let customer = this.topToolBarService.getCustomer();
 if (customer == null) {
   bDefine = false;
 } else {
    bDefine = true;
   }
}

我相信我已经在我的测试中模拟了服务功能,所以我希望它必须到达变量设置为“真”的其他部分。

TopToolBarService.ts

import { EventEmitter, Injectable, Output } from "@angular/core";

@Injectable()
export class TopToolBarService {
customer = null;

  getCustomer() {
    return this.customer;
  }
}

【问题讨论】:

  • 您能创建一个minimal, reproducible example,最好在 StackBlitz 或类似网站上吗? component.spec.tscomponent.ts 的其余部分是什么?

标签: angular typescript unit-testing


【解决方案1】:

您必须在运行代码之前配置测试模块。它不知道您的间谍对象,除非您将其作为导入传递给TestBed.configureTestingModule

https://angular.io/guide/testing#component-with-a-dependency

【讨论】:

    【解决方案2】:

    尝试在 beforeEach(async(() => ...) 中更新提供程序并将您的 mockedService 变量移到它的顶部:

    describe('Component TEST', () => {
       ...
       let mockToolBarService;
       ...
          beforeEach(async(() => {
          ...
          mockToolBarService = jasmine.createSpyObj(['getCustomer']);
          mockToolBarService.getCustomer.and.returnValue('king');
          TestBed.configureTestingModule ({
               ...
               providers: [ { provide: TopToolBarService, useValue: mockToolBarService } ]
               ...
    

    希望对你有帮助!

    【讨论】:

      【解决方案3】:

      更改您的提供者值

      beforeEach(() => {
         TestBed.configureTestingModule({
            declarations: [ UsersListComponent],
            providers: [{
               provide: TopToolBarService,
               useValue: jasmine.createSpyObj('TopToolBarService', ['getCustomer'])
            }],
            schemas:[CUSTOM_ELEMENTS_SCHEMA]
           });
           mockTopToolBarService = TestBed.get(TopToolBarService);
      
           mockTopToolBarService.getCustomer.and.returnValue(of([])); // mock output of function
         })
      
      

      【讨论】:

        【解决方案4】:

        您可以考虑使用ng-mocks 来避免使用所有样板来配置TestBed

        beforeEach(() => MockBuilder(UsersListComponent)
          .mock(TopToolBarService, {
            // adding custom behavior to the service
            getCustomer: jasmine.createSpy().and.returnValue('king'),
          })
        );
        
        it('should return data from service function', () => {
          const fixture = MockRender(UsersListComponent);
          // now right after the render the property should be true
          expect(fixtur.point.componentInstance.bDefine).toBe(true);
        }));
        

        【讨论】:

        【解决方案5】:

        @Pedro Bezanilla 的回答已经足够好了。鉴于服务是单例的,我认为这是大多数情况下的另一种代码更少的方式。

        不同之处在于configureTestingModule 没有提供提供程序配置。间谍是由 spyOn 针对从 TestBed 获取的服务对象设置的。

        调用 TestBed.inject 而不是 TestBed.get 是因为它自 v9.0.0 以来已被弃用。

        对于单例服务,这里是a doc in Angular website,为了完成,请记住this GitHub issue

        describe('Component TEST', () => {
          ...
          let mockToolBarService: TopToolBarService;
          ...
          beforeEach(waitForAsync(() => {
            TestBed.configureTestingModule({
              declarations: [ UsersListComponent ],
              schemas:[ CUSTOM_ELEMENTS_SCHEMA ]
            });
            mockTopToolBarService = TestBed.inject(TopToolBarService);
            spyOn(mockTopToolBarService, 'getCustomer').and.returnValue(of([]));
          }));
          ...
        

        【讨论】:

          猜你喜欢
          • 2020-04-19
          • 2022-01-22
          • 2021-09-18
          • 1970-01-01
          • 1970-01-01
          • 2017-06-25
          • 1970-01-01
          • 2020-07-10
          • 2015-11-29
          相关资源
          最近更新 更多