【问题标题】:Mocked function returns wrong value模拟函数返回错误值
【发布时间】:2022-01-23 17:42:35
【问题描述】:

我正在尝试模拟在我的组件中使用的服务。

这是我的组件:

import { Component, OnInit } from '@angular/core';
import { SimpleService } from './simple-service';

@Component({
  selector: 'app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  providers: [SimpleService],
})
export class AppComponent implements OnInit {
  public bar = false;
  
  constructor(private simpleService: SimpleService) {}

  ngOnInit(): void {
    this.bar = this.simpleService.foo();
  }
}

这是我的服务:

export class SimpleService {
    foo(): boolean {
        return true;
    }
}

这是我的茉莉花测试:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SimpleService } from './simple-service';

import { AppComponent } from './app.component';

describe('AppComponent', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;
  let mockSimpleService : jasmine.SpyObj<SimpleService>;

  beforeEach(async () => {
    mockSimpleService = jasmine.createSpyObj<SimpleService>('SimpleService', ['foo']);
    mockSimpleService.foo.and.returnValue(false)
    
    await TestBed.configureTestingModule({
      declarations: [AppComponent],
      providers: [{ provide: SimpleService, useValue: mockSimpleService }]
    }).compileComponents();
  });

  beforeEach(() => {
    mockSimpleService.foo.and.returnValue(false)
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('foobar', () => {
    expect(component.bar).toBe(true);
  });

  it('foobar mock', () => {
    mockSimpleService.foo.and.returnValue(false)
    expect(component.bar).toBe(false);
  });
});

如您所见,我尝试在不同位置模拟 foo 方法,但是“foobar”测试用例成功,而“foobar mock”测试用例失败。

如何模拟我的服务的foo 方法?

【问题讨论】:

  • 我通常做的是在模块创建后进行模拟并且工作正常。 await compileComponents(); let s = TestBed.inject(Service); jasmine.spyOn(s, 'fn').and.returnValue(false)
  • 通过让服务成为组件级提供者,使用测试替身变得更加复杂;这真的有必要吗?要么在模块/根级别提供服务,要么查看angular.io/guide/…
  • @Some random IT boy:我删除了对我的模拟的所有引用并使用了您的建议,如下所示:await TestBed.configureTestingModule({ declarations: [AppComponent], providers: [{ provide: SimpleService }] }).compileComponents(); const s : SimpleService = TestBed.inject(SimpleService); spyOn(s, 'foo').and.returnValue(false);,但它仍然不起作用。
  • 这能回答你的问题吗? Test component with a providers
  • 只在期待bar属性之前调用fixture.detectChanges();

标签: angular typescript unit-testing jasmine


【解决方案1】:

感谢@jonrsharpe 和@hoangdv,我找到了解决方案:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SimpleService } from './simple-service';

import { AppComponent } from './app.component';

describe('AppComponent', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [App Component],
      providers: [{ provide: SimpleService, useClass: SimpleService }]
    }).compileComponents();
  });

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

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('foobar', () => {
    fixture.detectChanges();
    expect(component.bar).toBe(true);
  });

  it('foobar mock', () => {
    const sps = fixture.debugElement.injector.get(SimpleService);
    spyOn(sps, 'foo').and.returnValue(false);
    fixture.detectChanges();
    expect(component.bar).toBe(false);
  });
});

现在foobarfoobar mock 测试用例都成功了。

【讨论】:

    猜你喜欢
    • 2023-03-26
    • 2011-02-20
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 2015-12-28
    相关资源
    最近更新 更多