node.js - 使用 chai 和 mocha 在 nodejs 中对 Observable 结果进行简单测试

标签 node.js testing mocha.js rxjs rxjs5

我正在使用 Nodejs、RxJS 和 Typescript 开发应用。

应用程序有一个返回字符串的 Observable 的函数

myObsFunction() : Observable<string> {
... do stuff
}

我希望能够做一个简单的测试来检查当我订阅这个函数时我得到了预期的字符串。我正在使用 chaimocha 所以我写了下面的测试用例

import { expect } from 'chai';
import 'mocha';

import {myObsFunction} from './my-source-file';

describe('myObsFunction function', () => {

    it('check myObsFunction', () => {
        const expectedString = 'abc';
        let receivedString: string;
        myObsFunction().subscribe(
            data => receivedString = data,
            error => console.error(error),
            () => expect(receivedString).to.equal(expectedString)
        )
    });

});

不幸的是,这个测试用例并没有像我预期的那样工作。即使在出现错误的情况下,它也始终表现得像已成功通过一样。我在 onCompleted 函数中编写的 expect 检查不会发出任何信号,即使 expectedString 不等于 receivedString 也是如此。 onCompleted 函数实际上被执行了(我可以看到这只是在 onCompleted 函数中添加了一条 console.log 指令)但是 expect 没有发出信号有错有错

有没有什么方法可以运行如此简单的测试,而不必开始使用调度程序和更复杂的机制?

最佳答案

测试逻辑看起来很合理,这是一个使用 mocha 和 chai 的工作示例。

console.clear() 
const Observable = Rx.Observable
mocha.setup('bdd');
const assert = chai.assert;
const should = chai.should();
const expect = chai.expect;
const done = mocha.done;


const myObsFunction = () => Observable.of('xyz');
const myAsyncObsFunction = () => Observable.timer(500).mapTo('xyz');

describe('RxJs Observable Test Examples', function() {

  it('should test the observable succeeds', function () {
    const expectedString = 'xyz';
    let receivedString: string;
    myObsFunction().subscribe(
      data => receivedString = data,
      error => console.error(error),
      () => {
        expect(receivedString).to.equal(expectedString);
      }  
    )
  });

  it('should test the observable fails', function () {
    const expectedString = 'abc';
    let receivedString: string;
    myObsFunction().subscribe(
      data => receivedString = data,
      error => console.error(error),
      () => {
        expect(receivedString).to.equal(expectedString);
      }  
    )
  });

  it('should test the async observable succeeds', function (done) {
    const expectedString = 'xyz';
    let receivedString: string;
    myAsyncObsFunction().subscribe(
      data => receivedString = data,
      error => console.error(error),
      () => {
        //expect(receivedString).to.equal(expectedString);
        if (receivedString !== expectedString) {
          return done(new Error("Failed match"));
        } else {
          return done();
        }
      }  
    )
  });

  it('should test the async observable fails', function (done) {
    const expectedString = 'abc';
    let receivedString: string;
    myAsyncObsFunction().subscribe(
      data => receivedString = data,
      error => console.error(error),
      () => {
        //expect(receivedString).to.equal(expectedString);
        if (receivedString !== expectedString) {
          return done(new Error("Failed match"));
        } else {
          return done();
        }
      }  
    )
  });
});

mocha.run();
<link href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.js"></script>
<div id="mocha"></div>


当 observable 从不触发时的误报

如果可观察对象从不触发,我遇到的一件事是误报。这是我用来克服该问题的一些辅助函数。请注意,take(1) 可确保触发已完成的事件,即使可观察对象本身并未完成。

console.clear() 
const Observable = Rx.Observable
mocha.setup('bdd');
const assert = chai.assert;
const should = chai.should();
const expect = chai.expect;

const subscribeAndTestValue = function (observable: Observable<any>, expected: any): string {
  let fail = '';
  let wasSubscribed = false;
  const sub = observable
    .take(1)
    .subscribe(
      (result) => {
        if (result !== expected) {
          fail = 'Subscription result does not match expected value';
        }
        wasSubscribed = true;
      },
      (error) => {
        fail = 'Subscription raised an error';
      },
      (/*completed*/) => {
        // When testing a single value,
        // need to check that the subscription was activated,
        // otherwise the expected value is never tested
        if (!wasSubscribed) {
          fail = 'Subscription produced no results';
        }
      }
    );
  sub.unsubscribe();
  return fail;
}

const subscribeAndTestNoDataEmitted = function (observable: Observable<any>): string {
  let fail;
  let wasSubscribed = false;
  const sub = observable
    .subscribe(
      (result) => {
        wasSubscribed = true;
      },
      (error) => {
        fail = 'Subscription raised an error';
      },
      (/*completed*/) => {
        if (wasSubscribed) {
          fail = 'Subscription produced values when none were expected';
        }
      }
    );
  sub.unsubscribe();
  return fail;
}

const emptyObservable = Observable.empty();
const nonCompletingObservable = Observable.interval(1000);
const emittingObservable = Observable.of('abc');

describe('RxJs Observable Test Examples', function() {

  it('should test the observable fires', function () {
    const expectedString = 'xyz';
    const failed = subscribeAndTestValue(emptyObservable, expectedString);
    expect(failed).to.equal('Subscription produced no results');
  });

  it('should test first observable value of a non-completing observable', function () {
    const expectedString = '0';
    const failed = subscribeAndTestValue(nonCompletingObservable, expectedString);
    expect(failed).to.equal('');
  });

  it('should test the observable does not fire', function () {
    const expectedString = 'xyz';
    const failed = subscribeAndTestNoDataEmitted(emittingObservable, expectedString);
    expect(failed).to.equal('Subscription produced values when none were expected');
  });
  
});

mocha.run();
<link href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.js"></script>
<div id="mocha"></div>

关于node.js - 使用 chai 和 mocha 在 nodejs 中对 Observable 结果进行简单测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47365114/

相关文章:

node.js - 如何将 cookie 与 superagent 一起使用?

node.js - MongoDB连接不断增加

javascript - 从 AS3 客户端运行 MongoDB 查询?

ruby-on-rails - 无法访问类 nil Rails 4 的对象

ios - testflightapp.com,它是如何工作的,我可以假设它是安全的并且工作时间更长吗?

unit-testing - 使用Mocha、Chai和Sinon来测试延迟 Action

javascript - 如何在aws lambda函数中使用setInterval

javascript - Grunt 启动 Node Server,然后打开浏览器

ruby-on-rails - RSpec 测试调用 ActiveMailer 模型

node.js - 告诉 Mocha 默认使用 CoffeeScript 文件