【问题标题】:Angular testing not invoking expectation resulting to "Spec has no expectation"Angular 测试不调用期望导致“规范没有期望”
【发布时间】:2019-09-18 23:42:36
【问题描述】:

我有一个对我的后端进行 HTTP 调用的服务,我正在尝试测试它是否会得到用户的响应,在运行测试时我得到一个 Spec has no expectation,即使我在订阅中有一个。所有这些测试都通过了,但 2 的输出为 SPEC HAS NO EXPECTATION

这是我的代码:

describe('Auth Service Testing', () => {
  let httpClientSpy: { get: jasmine.Spy };
  let authServ: AuthService;
  let authAct: AuthActions;
  let userAct: UserActions;
  let checkoutAct: CheckoutActions;
  let productAct: ProductActions;
  let store: Store<any>;
  let localStorageServ: LocalStorageService;
  let authResponse;
  const expectedUserResponse = {
    users: [],
    count: 25,
    current_page: 1,
    pages: 2
  };

  beforeEach(() => {
    httpClientSpy = jasmine.createSpyObj('HttpClient', ['get']);
    authServ = new AuthService(
      <any>httpClientSpy,
      authAct,
      userAct,
      checkoutAct,
      productAct,
      store,
      localStorageServ
    );
  });

  it('should get users response', () => {
    httpClientSpy.get.and.returnValue(asyncData(expectedUserResponse));

    authServ.authorized().subscribe((users) => {
      authResponse = users;
      expect(users).toEqual(jasmine.objectContaining({ users: [] }));
    });

  });

  it('should equal to expected users response', () => {
    expect(authResponse).toEqual(expectedUserResponse);
  });

  it('should return null if theres an error', () => {
    httpClientSpy.get.and.returnValue(asyncError(expectedUserResponse));
    authServ
      .authorized()
      .subscribe(() => {}, (error) => expect(error).toBe(null));
  });
});

另外,我遵循了 Angular HTTP 测试指南 angular test 我想知道这是一个错误还是其他什么。

因果报应:

Auth Service Testing
SPEC HAS NO EXPECTATIONS should return null if there's an error
SPEC HAS NO EXPECTATIONS should get users response
should equal to expected users response

更新

缺少的代码是这个expect(httpClientSpy.get.calls.count()).toBe(1);这很奇怪,我以为这个调用发出了一个http get请求httpClientSpy.get.and.returnValue(asyncError(expectedUserResponse));

但是在指南的错误测试中,他们没有这个。有人能解释一下吗?

来自朝鲜的很多爱。

【问题讨论】:

    标签: angular karma-jasmine angular-test


    【解决方案1】:

    使用订阅对 observable 进行单元测试真的很困难。单元测试将通过但应该失败的许多极端情况。即使您将done() 回调与finiazlier 或错误处理程序一起使用。

    当一个 observable 只发出 一个 预期结果时,你应该使用 Promise。

      it('should get users response', async () => {
        httpClientSpy.get.and.returnValue(asyncData(expectedUserResponse));
    
        const users = await = authServ.authorized().toPromise();
    
        expect(users).toEqual(jasmine.objectContaining({ users: [] }));
      });
    

    当一个 observable 发出多个值时,您可以转换为数组并仍然使用 Promise。

      it('should get users response', async () => {
        httpClientSpy.get.and.returnValue(asyncData(expectedUserResponse));
    
        const users = await = authServ.authorized().pipe(
            toArray()
        ).toPromise();
    
        expect(users).toEqual(jasmine.objectContaining([{ users: [] }]));
      });
    

    toPromise() 的优点是它总是可以解析。即使 observable 没有发出任何值,并且如果在 observable 中抛出任何未捕获的错误,它也会导致单元测试失败。

    【讨论】:

    • 这个可行,但为什么它是角度文档推荐这个。这更容易和简单。所以每次我测试任何可观察的东西时,我都会使用toPromise()
    • @aRtoo 我知道,但文档有误。他们的例子可能会失败。这就是经验和理论的区别。如果o 从不发射,o.subscribe(v =&gt; expect(v).toBe(1), () =&gt; done.fail(), ()=&gt; done());通过
    • 我一直在阅读一篇有角度的帖子,并阅读了有关订阅 HTTP 响应的投诉,所以这是真的,或者只是为了测试。再次感谢先生。你是山羊。
    • @aRtoo 它仅用于单元测试,这是因为 rxjs 如何将数据的发送和完成作为单独的事件处理。所以一个 observable 可以完成,可能不会完成,也可能不会发出任何东西。单元测试开发人员必须处理这些边缘情况,而人们必须不这样做。所以它会导致一些糟糕的单元测试,但切换到 Promise 会简化你的工作。这并不意味着您应该在应用程序中使用 Promise 而不是 observables。
    • 非常感谢。这现在澄清了一切。我会记住这一点。感谢先生的帮助。
    猜你喜欢
    • 1970-01-01
    • 2020-08-10
    • 2020-10-26
    • 2020-05-07
    • 2017-06-28
    • 1970-01-01
    • 1970-01-01
    • 2021-05-09
    • 1970-01-01
    相关资源
    最近更新 更多