无法使用大理石测试编写测试用例

unable to write a test case with marbel testing

我创建了这个函数,因为对于我的应用程序使用 http.post 发出的所有请求,这就是不同部分处理响应的方式。所以我没有复制代码,而是想创建一个函数。我想模拟错误处理并想到使用 marbel testing。虽然我可以看到测试用例 emits 一条错误消息,但测试仍然失败。我做错了什么

private editAnswerSubject: Subject<Result>;
subscribeToReturnedObservable(observable:Observable<any>, subject:Subject<Result>) {
    observable.subscribe((res) => {
        const ev = <HttpEvent<any>>(res);
        if (ev.type === HttpEventType.Response) {
          const isResponseStructureOK: boolean = this.helper.validateServerResponseStructure(ev.body);
          if (isResponseStructureOK) {
            const response: ServerResponseAPI = ev.body;
            subject.next(new Result(response.result, response['additional-info']));

          } else {
            subject.next(new Result(messages.error, messages.invalidStructureOfResponse));
          }
        }
      },
      (error: ServerResponseAPI) => { //THIS IS THE CODE I WANT TO TEST
        const errorMessage: string = this.helper.userFriendlyErrorMessage(error);
        subject.next(new Result(messages.error, errorMessage));    
      },
      () => { // observable complete
      });
  }

  editAnswer(answer: Answer): any {
    const observable = this.bs.editAnswer(answer)
    this.subscribeToReturnedObservable(observable,this.editAnswerSubject);
  }

到目前为止我写的测试是

fit('should call next for the subject if the response from the server is error', () => {
      const questionService:QuestionManagementService = TestBed.get(QuestionManagementService);
      const serverErrorResponse = {
        result: "error",
        ['additional-info']: "reason for error",
        ['http-status']: "304",
        ['http-status-text']: "not found"
      };
      const testScheduler = new TestScheduler((actual,expected)=>{
        expect(actual).toEqual(expected);
      });
      spyOn(questionService['editQuestionSubject'],'next');
      testScheduler.run(helpers=>{
        const { cold, expectObservable, expectSubscriptions } = helpers;
        const expectedMarble = '#|';//error
        const expectedIngridients = {a:serverErrorResponse};
        const observable = cold(expectedMarble,{},serverErrorResponse);

        questionService.subscribeToReturnedObservable(observable,questionService['editQuestionSubject']);
        const expectedResult = new Result(messages.error, 'Error code: 304. not found. error: reason for error');
        expect(questionService['editQuestionSubject'].next).toHaveBeenCalledWith(expectedResult);
      });

但是出现错误Expected spy next to have been called with [ Result({ result: 'error', additionalInfo: 'Error code: 304. not found. error: reason for error' }) ] but it was never called.

我可以在代码跟踪中看到收到了错误值。

subscribeToReturnedObservable called
got error from the Observable:  {result: "error", additional-info: "reason for error", http-status: "304", http-status-text: "not found"}

我不得不打电话给 flush。老实说,我不知道它为什么以及如何使事情起作用。从我能理解的原因来看,我正在以同步方式测试。所以我需要调用 flush 以便在 Observable 完成时调用断言 (expect)。

fit('should call next for the subject if the response from the server is error', () => {
  const questionService:QuestionManagementService = TestBed.get(QuestionManagementService);
  const serverErrorResponse = {
    result: "error",
    ['additional-info']: "reason for error",
    ['http-status']: "304",
    ['http-status-text']: "not found"
  };
  const testScheduler = new TestScheduler((actual,expected)=>{
    expect(actual).toEqual(expected);
  });
  spyOn(questionService['editQuestionSubject'],'next');
  testScheduler.run(helpers=>{
    const { cold, expectObservable, expectSubscriptions,flush } = helpers;
    const expectedMarble = '#|';//error
   // const expectedIngridients = {a:serverErrorResponse};
    const observable = cold(expectedMarble,null,serverErrorResponse);

    questionService.subscribeToReturnedObservable(observable,questionService['editQuestionSubject']);
    flush(); //THIS
    const expectedResult = new Result(messages.error, 'Error code: 304. not found. error: reason for error');
    expect(questionService['editQuestionSubject'].next).toHaveBeenCalledWith(expectedResult);
  });
});