【问题标题】:How to test a change on observable in service mock?如何测试服务模拟中可观察的变化?
【发布时间】:2019-08-23 11:43:03
【问题描述】:

我必须测试一个后端服务存根,它返回一个 observable。 存根方法:

public postStatus(handle: string): Observable<StatusReturn>{
    setTimeout(() => {
      this.result = {
        currentlyProcessedFileName: 'datei2.pdf',
        errParams: [],
        numFiles: 3,
        numFilesAlreadyProcessed: 1,
        numTasksBefore: 0,
        processingStatus: 1,
        technicalRetCode: 0
      };
    }, 5000);
    setTimeout(() => {
      this.result = {
        currentlyProcessedFileName: '',
        errParams: [],
        numFiles: 3,
        numFilesAlreadyProcessed: 3,
        numTasksBefore: -1,
        processingStatus: 2,
        technicalRetCode: 0
      };
    }, 10000);
    return of(this.result);
  }

附加信息:结果在服务级别初始化,所以 setTimeout 只是更新这些参数。

我已经尝试了很多,但我的“最接近”的方法如下:

fit('postStatus should return changeing Observable<StatusReturn> with correct second sample data after 5000ms', fakeAsync(() => {
    // WHEN
    const secondReturn = {
      currentlyProcessedFileName: 'datei2.pdf',
      errParams: [],
      numFiles: 3,
      numFilesAlreadyProcessed: 1,
      numTasksBefore: 0,
      processingStatus: 1,
      technicalRetCode: 0
    };
    let result;

    // DO
    service.postStatus('handle').subscribe((res) => {
      result = res;
    });
    tick(5001);

    expect(result).toEqual(secondReturn);
  }));

测试出现以下错误:

Expected $.currentlyProcessedFileName = '' to equal 'datei2.pdf'.
Expected $.numFilesAlreadyProcessed = 0 to equal 1.
Expected $.numTasksBefore = 1 to equal 0.
Expected $.processingStatus = 0 to equal 1.

左侧是初始数据(所以我从 observable 获取数据)和

Error: 1 timer(s) still in the queue.

表示第一次数据更新被触发。我可以通过将 tick(5001) 更改为 tick(4999) 并在队列中有两个计时器来批准这一点。

我正在寻找有关如何使用新的可观察值更新结果变量的建议。

【问题讨论】:

    标签: angular unit-testing asynchronous observable


    【解决方案1】:

    我认为您的功能正在做一些您想要的事情。 我们可以通过添加一些 console.log 语句来测试。

    service.postStatus('handle').subscribe((res) => {
        console.log('setting return');
        result = res;
    });
    console.log(`result is ${result}`);
    
    tick(5001);
    console.log('tick 5001 occurred');
    

    LOG: '设置返回'

    LOG: '结果未定义'

    LOG:'tick 5001 发生'

    这告诉我们您的订阅立即返回,因为这是我们看到的第一个控制台日志。由于计时器尚未触发,因此结果未定义。

    由于您返回一个 observable 并期望它有两个不同的结果,我想为您的测试方法建议一种稍微不同的方法。我们可以返回一个Subject&lt;StatusReturn&gt;,如下所示。

    public postStatus(handle: string): Observable<StatusReturn> {
        const currentStatus = new Subject<StatusReturn>();
    
        setTimeout(() => {
            this.result = {
                currentlyProcessedFileName: 'datei2.pdf',
                errParams: [],
                numFiles: 3,
                numFilesAlreadyProcessed: 1,
                numTasksBefore: 0,
                processingStatus: 1,
                technicalRetCode: 0
            };
            currentStatus.next(this.result);
        }, 5000);
        setTimeout(() => {
            this.result = {
                currentlyProcessedFileName: '',
                errParams: [],
                numFiles: 3,
                numFilesAlreadyProcessed: 3,
                numTasksBefore: -1,
                processingStatus: 2,
                technicalRetCode: 0
            };
            currentStatus.next(this.result);
        }, 10000);
        return currentStatus;
    }
    

    注意到我打电话给currentStatus.next(this.result) 告诉主题结果已经改变了吗?

    有了这个,你可以稍微改变你的测试看起来像

    fit('postStatus should return changing Observable<StatusReturn> with correct second sample data after 5000ms', fakeAsync(() => {
        // WHEN
        const secondReturn = {
            currentlyProcessedFileName: 'datei2.pdf',
            errParams: [],
            numFiles: 3,
            numFilesAlreadyProcessed: 1,
            numTasksBefore: 0,
            processingStatus: 1,
            technicalRetCode: 0
        };
        let result;
    
        // DO
        service.postStatus('handle').subscribe((res) => {
            result = res;
        });
    
        tick(5001);
        const firstResult = result;
    
        expect(result).toEqual(secondReturn);
    
        tick(5001); // clear the queue
        expect(result).not.toEqual(firstResult);
    }));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-05
      • 2019-09-21
      • 2015-08-20
      • 1970-01-01
      • 2017-12-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多