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

jest: How to teardown after (just) an individual test

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
    }
    ...
}

上面的问题...

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

潜在(非理想)解决方案

一个解决方案就是将 delete global.foo 添加到我的 afterEach 中。它并不真的需要在每次测试后都是 运行,但它也没有任何害处。另一种解决方案是单独进行特定测试,以便 afterEach 仅适用于它。但这似乎也不理想 - 如果该测试属于其他测试,则它可能会保留在其他测试中。

我的问题:

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

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

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

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
        });
    });

beforeEachafterEach 可以脱糖为 try..finally:

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

这也允许异步测试,但需要用 async 而不是 done 编写。