繁体   English   中英

在Ava测试中使用RxJS延迟运算符

[英]the use of the RxJS delay operator within Ava tests

我是一个JavaScript程序的作者,该程序需要针对许多测试执行。 我发现每个测试都遵循类似的格式,因此使用工厂函数生成测试是适当的。

工厂函数称为testFactory,并在下面的代码中显示。 它由数据数组调用,一旦添加了我的应用程序逻辑,该数据数组将指示工厂如何构建特定的测试。 工厂功能也负责执行测试。

我选择RxJS是为了在传递给工厂的数据中包含“延迟”字符串时实现两秒的延迟。 (我之前在实现中的尝试使用了Promise,但是我无法使这种方法起作用。)如您所见,这是通过使用Rx延迟运算符实现的。

选择Ava是因为它具有使用RxJS的声誉。 如您所见,我正在从可观察对象的订阅中调用Rx主题。

在我的实际应用程序代码中,此预订对实现我的应用程序逻辑的状态机进行调用,并且通过在状态机上的回调方法中对主题的下一个方法的调用将来自状态机的数据馈送到主题中。 这就是为什么我不能简单地将我的可观察对象直接插入Ava测试方法中,而必须经历一个主题。 选择一个主题而不是一个可观察的主题,因为该主题允许从其定义之外调用其下一个完整方法。

我从下面的代码中删除了我的应用程序逻辑,以免将该问题与这些细节混淆。 问题是从数据数组中删除“延迟”字符串时。 当此代码与不包含延迟的数据一起运行时,测试不会通过:

const data = [
  { r: 'c' },
  { l: 'c' },
  { l: 'n' },
  { l: 'c' }
];

它失败了: Test finished without running any assertions.

当数据数组中没有“延迟”时,如何获得通过? 当数据阵列中没有“延迟”时,为什么这会失败? 谢谢。

const ava = require('ava');
const { test } = ava;

const Rx = require('rxjs/Rx');
const { Observable, Subject } = Rx;

const data = [
  { r: 'c' },
  { l: 'c' },
  { l: 'n' },
  'delay',
  { l: 'c' }
];

const testFactory = (data) => {
  let subject = new Subject();

  // This code adds a delay property to each item which passes through, adding a
  // delay value based on a cumulative delay value maintained by the scan
  // operator. Items which are simply delays are marked with a 'skip' property
  // in the scan and skipped in the flatMap. Once the delay has been performed
  // by the delay operator, the added delay property is deleted. If there is a
  // simpler way in Rx to achieve this functionality, I'm open to suggestions
  // on refactoring this code. :-)
  const source = Observable.from(data)
    .scan((acc, val) => {
      if (val === 'delay') {
        return { skip: true, delay: acc.delay + 2000 };
      }
      return Object.assign(val, { delay: acc.delay });
    }, { delay: 0 })
    .flatMap((e) => {
      if (e.skip) {
        return Observable.empty();
      } else {
        return Observable.of(e)
          .delay(e.delay)
          .map(e => { delete e.delay; return e; });
      }
    });

  // This is the subscribe block which in my application called my state
  // machine. Since the state machine has been removed, the Subject is called
  // directly, instead of calling it from the callback tot the state machine.
  // Either way, the same problem exists. 
  source
    .subscribe({
      next: e => {
        subject.next(e);
      },
      complete: () => {
        subject.complete();
      }
    });

  // This test always passes. When the 'delay' is removed, the failure would
  // indicate to me that its never called.  
  test('', t => {
    // t.plan(1);
    return subject
      .map((n) => {
        t.true(true);
      });
  });
};

testFactory(data);

注意:有趣的是,当删除Ava的导入以及在其下一行导入Ava的测试函数的行,并且对测试函数的调用被替换为对该主题的常规RxJS订阅时,该代码可在有和没有'delay的情况下工作'数据结构中的字符串:

  // test('', t => {
  //   // t.plan(1);
  //   return subject
  //     .map((n) => {
  //       t.true(true);
  //     });
  // });

  subject.subscribe((v) => {
    console.log(JSON.stringify(v));
  });

这是否表明问题出在我使用Ava?

我对RxJS,可观察对象或主题并不十分熟悉,但是在Test finished without running any assertions.有一条线索是在Test finished without running any assertions.

当您返回一个observable,promise或使用test.cb(t => t.end())时,AVA测试可以是同步的,也可以是异步的。 如果在测试完成之前未运行任何断言,则AVA也会使测试失败。

就您而言,AVA似乎确定您的测试是同步的。 您应该确保它是异步的,并且仅在数据被完全消耗时才结束。

暂无
暂无

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

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