簡體   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