简体   繁体   English

单元测试Angular服务

[英]Unit test Angular service

I'm struggling with testing a service in an Angular project. 我正在努力在Angular项目中测试服务。 The service is pretty small but i can't figure out how to test the observer in the class. 该服务非常小,但是我不知道如何在课堂上测试观察者。

I am trying to test a method of this class. 我正在尝试测试此类的方法。 The public methods must do what it promises to do. 公共方法必须按照其承诺做。 When I call the 'pop' method, the test fails. 当我调用“ pop”方法时,测试失败。 Since the pop method is public and has a Message as return values, this method should return a message after invoke it. 由于pop方法是公共方法,并且具有Message作为返回值,因此该方法在调用消息后应返回一条消息。 The underlying code is less relegant in the case of testing. 在测试的情况下,基础代码不太重要。

The reason the test fails is because the observer is still undefined at that moment. 测试失败的原因是因为那时观察者仍然不确定。 I suggest that the reason is because the callback method is not executed at the moment when i call the pop method in the test, thus the addMessage observer is not intialized yet. 我建议原因是因为在测试中调用pop方法时未执行回调方法,因此addMessage观察器尚未初始化。

Since I have just started on this project, I am cautious about assumptions about the code. 由于我刚开始这个项目,因此我对有关代码的假设持谨慎态度。 Does anyone have a suggestion on how I could test this code? 有人对我如何测试此代码有建议吗?

Is it right that the pop method is public or should it be private? pop方法是公共的还是应该私有的是正确的吗?

Edit: The pop method is used by a few other classes an can't be private. 编辑:pop方法由其他一些类使用,不能私有。 My question is actualy: Is this implementation of this service right? 我的问题实际上是:此服务的这种实现对吗?



    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;
      }
    }

The Test: 考试:

import {Message} from 'primeng/components/common/api';
    import {FeedBackService} from './feedback.service';


    fdescribe('Service: Feedback', () => {

      let feedbackService: FeedBackService;
      const MESSAGE: Message = {severity: 'This is a message', summary: 'Title', detail: 'Body'};
      const SEVERITY = 'severity';
      const SUMMARY = 'summary';
      const DETAIL = 'detail';

      beforeEach(() => {
        feedbackService = new FeedBackService();
      });



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

The Error: 错误:

在此处输入图片说明

Like any Observable, obsAddMessage isn't executed until subscribed to, and therefore as you demonstrated the observer is still undefined if you attempt to push a new value in before subscribing. 与任何Observable一样, obsAddMessage直到订阅obsAddMessage执行,因此,如您所展示的,如果您尝试在订阅前将新值推入,则观察者仍未定义。 The solution is simply to set up a subscribe before calling feedbackService.pop() . 解决方案就是在调用feedbackService.pop()之前先建立一个订阅。

I set up a simple Stackblitz to show what I mean. 我设置了一个简单的Stackblitz来说明我的意思。 The spec from that Stackblitz is: 该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);
});

I hope this helps. 我希望这有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM