【问题标题】:Unit test Angular service单元测试 Angular 服务
【发布时间】:2019-05-06 18:27:03
【问题描述】:

我正在努力测试 Angular 项目中的服务。 服务很小,但我不知道如何在课堂上测试观察者。

我正在尝试测试这个类的一个方法。公共方法必须做它承诺做的事情。当我调用“pop”方法时,测试失败。 由于 pop 方法是公共的并且有一个 Message 作为返回值,所以这个方法应该在调用它之后返回一个消息。在测试的情况下,底层代码的相关性较低。

测试失败的原因是此时观察者仍未定义。我建议原因是因为我在测试中调用pop方法的那一刻没有执行回调方法,因此addMessage观察者还没有初始化。

由于我刚刚开始这个项目,我对代码的假设持谨慎态度。 有人对我如何测试这段代码有什么建议吗?

pop方法是公有还是私有?

编辑: pop 方法被其他一些不能私有的类使用。 我的问题实际上是:这个服务的实现对吗?



    import { Injectable } from '@angular/core';
    import { Observable } from 'rxjs';
    import { share} from 'rxjs/operators';
    import { Observer } from 'rxjs';
    import { Message } from 'primeng/components/common/api';


    @Injectable()
    export class FeedBackService {
      obsAddMessage: Observable;
      obsClearMessages: Observable;
      /** @internal */
      private clearMessages: Observer;
      private addMessage: Observer;

      /**
       * Creates an instance of FeedBackService.
       */
      constructor() {
        this.obsAddMessage = new Observable(observer => this.addMessage = observer).pipe(share());
        this.obsClearMessages = new Observable(observer => this.clearMessages = observer).pipe(share());
      }


      /**
       * Synchronously create and show a new message instance.
       *
       * @param {(string | Message)} type The type of the message, or a Message object.
       * @param {string=} title The message title.
       * @param {string=} body The message body.
       * @returns {Message}
       *          The newly created Message instance.
       */
      pop( type: string | Message, title?: string, body?: string ): Message {
        const message: any = typeof type === 'string' ? {severity: type, summary: title, detail: body} : type;

        if (!this.addMessage) {
          throw new Error('No Containers have been initialized to receive messages.');
        } else {
          this.addMessage.next(message);
        }
        return message;
      }
    }

测试:

从'primeng/components/common/api'导入{Message}; 从'./feedback.service'导入{FeedBackService}; fdescribe('服务:反馈', () => { 让feedbackService:FeedBackService; const MESSAGE: Message = {severity: 'This is a message', summary: 'Title', detail: 'Body'}; const SEVERITY = '严重性'; 常量总结 = '总结'; const DETAIL = '详细信息'; beforeEach(() => { 反馈服务 = 新的反馈服务(); }); it('#pop 传入消息时应该返回消息', () => { 让 returnMessage = feedbackService.pop(MESSAGE); 期望(returnMessage).toEqual(MESSAGE); }); });

错误:

【问题讨论】:

  • 如果该方法是私有的,您将无法对其进行测试。保持公开。
  • @rrd 这不是真的而且很危险:将您的方法标记为私有并不能防止副作用。 某些方法在作用不大时可以忽略,但您应该始终测试您的代码。最后,你仍然可以测试私有方法,因为 Javascript 不理解私有成员的概念。
  • 至于OP,你读过the documentation about testing的全文吗?
  • 我会使用一个主题,而不是像这样新建一个 observable;请参阅我的博文blog.jonrshar.pe/2017/Apr/09/async-angular-data.html 和后续测试(注意是HttpClient 之前的)。
  • 我在现有代码上编写测试,不能就这样更改。我自己也不会这样写代码

标签: javascript angular unit-testing jasmine observable


【解决方案1】:

像任何 Observable 一样,obsAddMessage 在订阅之前不会执行,因此正如您所展示的,如果您在订阅之前尝试推送新值,则观察者仍然是未定义的。解决方法就是在调用feedbackService.pop()之前设置一个订阅。

我设置了一个简单的Stackblitz 来表达我的意思。 Stackblitz 的规范是:

it('#pop should return the message when passing in a message', () => {
  feedbackService.obsAddMessage.subscribe(message => console.log(message));
  let returnMessage = feedbackService.pop(MESSAGE);
  expect(returnMessage).toEqual(MESSAGE);
});

我希望这会有所帮助。

【讨论】:

  • 感谢您的解决方案,这解决了我的问题。观察者 observalbe 的概念现在对我来说已经完全清楚了!
猜你喜欢
  • 2017-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
  • 2017-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多