【问题标题】:How to run unit test case for toast message in angular service?如何在角度服务中运行 toast 消息的单元测试用例?
【发布时间】:2022-01-06 17:37:36
【问题描述】:

我正在使用基于 Angular 12 的应用程序。我有一个名为 notification 的服务,它处理来自 ngx-toastr 库的 toast 消息。

这是该服务的样子:

export class NotificationService {
  constructor(private toastr: ToastrService) {}

  showSuccess(message: string = 'Success ', note: string = ''): void {
    this.toastr.success(message, note);
  }

  showError(message: string = 'Error ', note: string = 'Try again'): void {
    this.toastr.error(message, note, {
      timeOut: 3000,
    });
  }
}

服务方法运行良好,但是当我尝试为它们实施测试时,我收到以下错误:

NotificationService should test "showSuccess" method FAILED

Error: <spyOn> : could not find an object to spy upon for success()

这些是测试:

describe('NotificationService', () => {
  let notificationService: NotificationService,
    httpTestingController: HttpTestingController,
    toastrService: ToastrService,
    notificationServiceSpy: any;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [CommonModule, HttpClientTestingModule, ToastrModule.forRoot()],
      declarations: [],
      providers: [{ provide: ToastrService, useValue: toastrService }],
    }).compileComponents();
    notificationService = TestBed.inject(NotificationService);
    httpTestingController = TestBed.inject(HttpTestingController);
    toastrService = TestBed.inject(ToastrService);
  });

  it('should be created', () => {
    expect(notificationService).toBeTruthy();
  });

  it('should test "showSuccess" method', () => {
    spyOn(toastrService, 'success').and.callThrough();
  });

  afterEach(() => {
    httpTestingController.verify();
  });
});

感谢任何帮助。谢谢!

【问题讨论】:

    标签: angular unit-testing jasmine angular-test angular-toastr


    【解决方案1】:

    您收到该消息是因为当您这样做时:

    providers: [{ provide: ToastrService, useValue: toastrService }],
    

    在那个时间点,toastrService 未定义,然后当您执行 spyOn(toastrService, 'success'); 时,没有成功方法可被监视,因为 toastrService 未定义。

    我会嘲笑toastrService

    进行以下更改,注意以!!开头的行。

    describe('NotificationService', () => {
      let notificationService: NotificationService,
        httpTestingController: HttpTestingController,
        // !! change this line to this
        toastrService: jasmine.SpyObj<ToastrService>,
        notificationServiceSpy: any;
    
      beforeEach(async () => {
        // !! add a new spy object before each test, now toastrService is not undefined
        toastrService = jasmine.createSpyObj<ToastrService>('ToasterService', ['error', 'success']);
        await TestBed.configureTestingModule({
          imports: [CommonModule, HttpClientTestingModule, ToastrModule.forRoot()],
          declarations: [],
          providers: [
           // !! provide NotificationService to the TestBed module because it is under test
           NotificationService,
           { provide: ToastrService, useValue: toastrService }],
        }).compileComponents();
        notificationService = TestBed.inject(NotificationService);
        httpTestingController = TestBed.inject(HttpTestingController);
        // !! don't need the below line, we already have access to the spy object
        // toastrService = TestBed.inject(ToastrService);
      });
    
      it('should be created', () => {
        expect(notificationService).toBeTruthy();
      });
    
      it('should test "showSuccess" method', () => {
        // !! you should not spyOn this anymore, toastrService has methods error
        // and success now which are both spies.
        // spyOn(toastrService, 'success').and.callThrough();
        // !! call the method
        service.showSuccess('hello world', 'hello');
        expect(toastrService.success).toHaveBeenCalledWith('hello world', 'hello');
      });
    
      afterEach(() => {
        httpTestingController.verify();
      });
    });
    

    【讨论】:

    • 非常感谢您的详细回答。一个问题,既然不需要'httpTestingController',我们还有用'afterEach'吗?
    • 如果你的服务没有注入HttpClient,你就不需要HttpClientTestingModuleHttpTestingController。查看此链接以获取学习 Angular 测试的良好资源:testing-angular.com
    • 谢谢,但这里使用 'afterEach' 还有其他原因吗?
    • 您拥有的 afterEach 确保队列中没有 http 调用。我认为不需要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-10
    • 1970-01-01
    • 2020-01-15
    • 1970-01-01
    • 2020-04-13
    • 2018-03-15
    相关资源
    最近更新 更多