簡體   English   中英

如何嵌套 Jest 測試

[英]How to nest Jest tests

我有一種情況,我需要創建一個調用 function 並檢查其返回值的測試。 它返回一個 object 所以我必須遍歷它並檢查 100 個左右的值是否正確。 如果其中一個失敗了,我想知道是哪一個。

我無法弄清楚如何使用 vanilla Jest 執行此操作,以便測試是獨立的,並且我會在失敗時收到有意義的錯誤消息。

例如,我可以這樣做:(偽代碼來說明,不是實際代碼)

describe('Test for function A', () => {
    beforeAll('Create class instance', () => {
        this.inst = new MyClass();
    });

    test('Call function with no parameters', () => {
        const value = this.inst.run();

        for (each key=value) {
            expect(value).toBe(correct); // on failure, doesn't tell me the key, only the value
        }
    });
});

這樣做的問題是,如果valuecorrect ,則錯誤消息不是很有幫助,因為它沒有告訴我 100 個值中的哪個有問題。

我無法更改為test.each()因為我收到一個錯誤消息,說我有嵌套的test()調用,這是不允許的。

如果我使用內部test()並將父test()更改為describe()則代碼變為:

describe('Test for function A', () => {
    beforeAll('Create class instance', () => {
        this.inst = new MyClass();
    });

    describe('Call function with no parameters', () => {
        const value = this.inst.run();

        for (each value) {
            test(`Checking ${value.name}`, () => {
                expect(value).toBe(correct);
            });
        }
    });
});

這會給我一個詳細的錯誤消息,除了this.inst.run()在測試設置期間被調用,在this.instbeforeAll()設置之前,所以它失敗了。 (Jest 首先運行所有describe()塊,然后beforeAll()test() 。這意味着我首先在describe()塊中調用this.inst.run() ,然后beforeAll()塊創建 class 實例。 )

有什么方法可以實現嗎? 要進行需要在所有子測試之間創建和共享 object 的測試,調用 function 的測試組來獲取該組的數據,然后在組內進行一堆測試?

是的,可以根據describetest塊的執行順序:

describe("Test for function A", () => {
  this.inst = new MyClass();
  afterAll("Create class instance", () => { //--> use this instead of beforeAll
    this.inst = new MyClass();
  });

  test("Should be defined", () => {
    //--> at least one test inside describe
    expect(inst).toBeTruthy();
  });

  describe("Call function with no parameters", () => {
    const value = this.inst.run();

    test("Should be defined", () => {
      //--> at least one test inside describe
      expect(value).toBeTruthy();
    });

    for (/*...each value */) {
      test(`Checking ${value.name}`, () => {
        expect(value).toBe(correct);
      });
    }
  });
});

我想出了一個解決方法。 這有點hacky,但它似乎工作。 本質上,您使用承諾來包裝您感興趣的值,因此一個測試將坐在那里await另一個測試的結果。

顯然,這僅適用於並行運行測試,或者如果順序排序使得 promise 在等待之前解決。

下面唯一的技巧是將await放置在beforeAll()塊中,以便該值可用於該describe()部分中的所有測試。 這避免了在每個單獨的測試中await的需要。

這樣做的好處是測試設置(創建對象)在test()中,因此會捕獲異常,並且檢查本身( expect().toBe() )在單獨的測試中,因此測試名稱可以是設置為描述性的東西。 否則,如果您的expect()調用在 for 循環中,則當一個失敗時,無法確定哪個數組條目有問題。

僅僅因為您無法在expect()調用上提供描述(與其他測試框架不同),這是很多工作,但如果您被 Jest 困住,那么這至少可以工作。 希望有一天他們會添加一個符合預期的描述來避免這一切。

這是一些示例偽代碼:

describe('Test for function A', () => {
    let resolveValue;
    let promiseValue = new Promise(resolve => resolveValue = resolve);

    describe('Create class instance', () => {
        test('Run processing', () => {
            this.inst = new MyClass();
            // inst.run() is now called inside a test(), so any failures will be caught.
            const value = this.inst.run();
            resolveValue(value); // release 'await promiseValue' below
        });
    });

    describe('Call function with no parameters', () => {
        let value; // this is global within this describe() so all tests can see it.

        beforeAll(async () => {
            // Wait for the above test to run and populate 'value'.
            value = await promiseValue;
        });

        for (each value) {
            // Check each value inside test() to get a meaningful test name/error message.
            test(`Checking ${value.name}`, () => {
                // 'value' is always valid as test() only runs after beforeAll().
                expect(value).toBe(correct);
            });
        }
    });
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM