使用具有Promises和angular的TestScheduler测试RxJS

时间:2016-06-16 16:57:39

标签: javascript angularjs reactjs rxjs

我在使用RxJS和Angular(而不是Angular 2)时遇到一个小问题,我确信这表明我做错了什么,但我不确定是什么。

我有一个函数可以创建一个我想测试的rx.Observable流。该功能的简化版本如下:

ResourceCollection.prototype.rxFetch = function() {
    var scheduler = this.injectedScheduler;

    var result = functionThatReturnsAnObservable(theseParams).concatMap(function(items) {
        var promises = _.map(readFromExternal(items), function(promise) {
            // results of this promise should be ignored
            return Rx.Observable.fromPromise(promise, scheduler);
        });
        promises = promises.concat(_.map(items, function(item) {
            // callEvent returns EventResult, these values should be passed on
            return Rx.Observable.fromPromise(callEvent(item), scheduler);
        }));
        return promises;
    }).concatMap(function(x) { return x; }).filter(function(res) {
        return (res instanceOf EventResult);
    }).toArray();

    return result;
});

我的测试功能如下:

describe('query', function() {
  var customers;
  var scheduler;

  beforeEach(function() {
      scheduler = new Rx.TestScheduler();
            
      customers = new ResourceCollection({
          url: '/api/customers',
          keyName: 'CustomerId',
          globalActions: {
              rxQuery: { method: 'GET', isArray: true }
          }
      });
      $httpBackend.whenGET('/api/customers/rxQuery').
  respond(function() {
          return [200, [
              { CustomerId: 1, Name: 'Brian', Region: 'North' },
              { CustomerId: 2, Name: 'Ravi', Region: 'East' },
              { CustomerId: 3, Name: 'Ritch', Region: 'East' },
              { CustomerId: 4, Name: 'Jeff', Region: 'West' },
              { CustomerId: 5, Name: 'Brandon', Region: 'West' }
          ]];
      });
  });
      
  it('rxFetch customers', function(done) {
    var vals;
    customers.injectedScheduler = scheduler
    var result = customers.rxFetch();
            
    result.subscribe(function(values) {
        vals = values;
    });
            
    $httpBackend.flush();
    
    // my question is here - what can I do to get rid of this loop?
    while (vals == null) {
        scheduler.advanceBy(100);
        $rootScope.$apply();
    }
            
    scheduler.start();

    expect(vals.length).toEqual(5);
    expect(vals[0]).toBe(customers[0]);
    done();
  });
      
});

问题很简单 - 当测试中的while循环在那里时,测试将产生正确的结果(这是一个包含所有callEvent函数结果的数组)。使用scheduler.scheduleAbsolute(或其他一些此类调用)与$ rootScope.app apply替换while循环,并且只有callEvent函数中的一个promise将完成。调用它两次,其中两个将完成等(因此while循环)。

但是while循环非常难看 - 而且我确信必须有一种更清晰的方法来让这个测试通过。非常感谢任何能指出正确方向的人。

0 个答案:

没有答案