开玩笑:如何在(仅)个人测试后拆卸

Tim*_*Tim 10 javascript testing teardown jestjs

jest提供afterEachbeforeEachafterAllbeforeAll要完成安装和拆卸的逻辑。我想做的是在一次特定测试后清理。考虑以下:

describe("a family of tests it makes sense to group together", () => {
    ...
    test("something I want to test", () => {
        // some setup needed for just this test
        global.foo = "bar"
        
        // the test
        expect(myTest()).toBe(true)

        // clear up
        delete global.foo
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

上面的问题...

如果上述测试由于某种原因失败,则delete global.foo永远不会运行。这意味着它之后的所有测试可能都会失败。我没有看到 1 个测试失败,而是看到大量测试失败,这可能会令人困惑。

潜在(非理想)解决方案

一种解决方案是添加delete global.foo到我的afterEach. 不需要在每次测试后都运行它,但它也没有任何危害。另一种解决方案是单独放置特定的测试,以便afterEach仅适用于它。但这似乎也不理想 - 如果该测试属于其他测试,那么它就不可能与它们一起存在。

我的问题:

有没有办法只为特定测试运行拆卸逻辑(而不在实际测试中运行它)。在我的特定用例中,第一个概述的解决方案很好,但我可以想象可能存在需要更细粒度控制的情况。例如,如果我的拆卸方法需要很长时间,我就不想重复很多次,因为这会减慢整个测试套件的速度。

小智 6

我知道这是一个老问题,但对于任何将来偶然发现这一挑战的人来说,这是我很久以前写的一个小库,名为jest-after-this,它就是这样做的:

import { afterThis } from 'jest-after-this';

it('should do something that requires a cleanup', () => {
  global.foo = 'something';
  afterThis(() => {
    delete global.foo;
  });

  // ... rest of test here can fail, the cleanup method will run anyways
});
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助 :)


Est*_*ask 5

在许多情况下afterEach,即使其中一个测试需要,测试也可以共享一个公共清理,只要它不影响其他测试。

否则,这就是块结构的责任。一个或多个测试可以与嵌套分组,describe以拥有自己的afterEach, etc 块,唯一的缺点是它使报告不那么漂亮:

describe("a family of tests it makes sense to group together", () => {
    ...
    describe("something I want to test", () => {
        beforeEach(() => {
            global.foo = "bar"
        });
   
        test("something I want to test", () => {
            expect(myTest()).toBe(true)
        }

        afterEach(() => {    
            delete global.foo
        });
    });
Run Code Online (Sandbox Code Playgroud)

beforeEach并且afterEach可以脱糖为try..finally

test("something I want to test", () => {
    try {
        global.foo = "bar"
        
        expect(myTest()).toBe(true)
    } finally {
        delete global.foo
    }
})
Run Code Online (Sandbox Code Playgroud)

这也允许异步测试,但需要使用async而不是done.