Jest/Testing 库测试套件中的意外 afterAll 执行
Unexpected afterAll execution in Jest/Testing Library test suite
我正在测试 React 组件中的一些异步行为,包括加载和错误状态。我通过使用设置状态的不同 describe
块来接近不同的状态,如下所示:
jest.spyOn(global, 'fetch');
describe('The App', () => {
const promiseWithDelay = (json, delay=0) =>
new Promise(resolve =>
setTimeout(
() => resolve({
ok: true,
json: () => json
}), delay
)
);
describe('given data loading', () => {
beforeEach(async () => {
global.fetch.mockImplementationOnce(() =>
promiseWithDelay(someData, 50)
);
await waitFor(() => render(<App />));
});
// ... successful tests for a loading state here
});
describe('some other tests', () => {
// ... more setup and other tests here
});
});
我正在通过模拟创建加载状态 fetch
测试全部通过,但我得到 Warning: Can't perform a React state update on an unmounted component.
错误,我认为这是因为第一个描述块中的 render
在第二个 describe
块开始 运行.
为了清除错误,我原本想在第一个describe
块中包含一个afterAll
函数来等待创建加载状态的Promise
解析,像这样:
describe('The App', () => {
// ... etc
describe('given data loading', () => {
beforeEach(async () => {
// ... etc
});
// ... successful tests for a loading state here
afterAll(async () => {
await waitFor(() => {
expect(screen.queryByTestId('some-rendered-content')).toBeInTheDocument();
});
});
});
describe('some other tests', () => {
// ... more setup and other tests here
});
});
这并没有清除错误,但是将 afterAll
函数更改为 afterEach
函数就可以了。
完全困惑,我添加了一些控制台日志记录以查看何时发生了什么,并发现了这一点:
// afterEach console logs
beforeEach: Starting loading test
test: Testing loading
afterEach: Cleaning up from loading test
afterEach: Waiting for content to render
afterEach: Waiting for content to render
afterEach: Cleaned up from loading test
some other test: Starting next test
// afterAll console logs
beforeEach: Starting loading test
test: Testing loading
afterAll: Cleaning up from loading test
afterAll: Waiting for content to render
(console.error): Warning: Can't perform a React state update on an unmounted component. (etc.)
afterAll: Waiting for content to render
afterAll: Waiting for content to render
... afterAll: Waiting for content to render logs many times here
some other test: Starting next test
谁能解释这里的操作顺序以及可能导致 afterAll
而不是 afterEach
警告的原因?
该警告意味着被测组件具有异步副作用(在此测试套件中由 fetch
表示),某些测试未等待这些副作用。
afterAll
应用于各自 describe
内的一组测试,如果有多个测试,其中一些不会受到 waitFor
在 afterAll
提供。
正如与测试框架的集成所预期的那样,React Testing Library 进行了清理以使测试不相互影响,afterEach
是正确的地方。正如 the documentation 所述,
Cleanup is called after each test automatically by default if the testing framework you're using supports the afterEach global (like mocha, Jest, and Jasmine).
编写测试的正确方法是在 RTL 清理之前等待组件内部的副作用完成。这需要在每个测试中等待至少与副作用持续时间(50 毫秒)相同的时间,并且需要更长的时间才能刷新承诺。 waitFor
的使用允许不依赖实现细节。由于副作用会影响测试结果,waitFor
的正确位置是 beforeEach
或测试本身,而不是 afterEach
或 afterAll
。
此外 await waitFor(() => render(<App />))
没有任何用处,因为它只对抛出错误的函数有效,最常见的是断言。可以简化为render(<App />)
.
我正在测试 React 组件中的一些异步行为,包括加载和错误状态。我通过使用设置状态的不同 describe
块来接近不同的状态,如下所示:
jest.spyOn(global, 'fetch');
describe('The App', () => {
const promiseWithDelay = (json, delay=0) =>
new Promise(resolve =>
setTimeout(
() => resolve({
ok: true,
json: () => json
}), delay
)
);
describe('given data loading', () => {
beforeEach(async () => {
global.fetch.mockImplementationOnce(() =>
promiseWithDelay(someData, 50)
);
await waitFor(() => render(<App />));
});
// ... successful tests for a loading state here
});
describe('some other tests', () => {
// ... more setup and other tests here
});
});
我正在通过模拟创建加载状态 fetch
测试全部通过,但我得到 Warning: Can't perform a React state update on an unmounted component.
错误,我认为这是因为第一个描述块中的 render
在第二个 describe
块开始 运行.
为了清除错误,我原本想在第一个describe
块中包含一个afterAll
函数来等待创建加载状态的Promise
解析,像这样:
describe('The App', () => {
// ... etc
describe('given data loading', () => {
beforeEach(async () => {
// ... etc
});
// ... successful tests for a loading state here
afterAll(async () => {
await waitFor(() => {
expect(screen.queryByTestId('some-rendered-content')).toBeInTheDocument();
});
});
});
describe('some other tests', () => {
// ... more setup and other tests here
});
});
这并没有清除错误,但是将 afterAll
函数更改为 afterEach
函数就可以了。
完全困惑,我添加了一些控制台日志记录以查看何时发生了什么,并发现了这一点:
// afterEach console logs
beforeEach: Starting loading test
test: Testing loading
afterEach: Cleaning up from loading test
afterEach: Waiting for content to render
afterEach: Waiting for content to render
afterEach: Cleaned up from loading test
some other test: Starting next test
// afterAll console logs
beforeEach: Starting loading test
test: Testing loading
afterAll: Cleaning up from loading test
afterAll: Waiting for content to render
(console.error): Warning: Can't perform a React state update on an unmounted component. (etc.)
afterAll: Waiting for content to render
afterAll: Waiting for content to render
... afterAll: Waiting for content to render logs many times here
some other test: Starting next test
谁能解释这里的操作顺序以及可能导致 afterAll
而不是 afterEach
警告的原因?
该警告意味着被测组件具有异步副作用(在此测试套件中由 fetch
表示),某些测试未等待这些副作用。
afterAll
应用于各自 describe
内的一组测试,如果有多个测试,其中一些不会受到 waitFor
在 afterAll
提供。
正如与测试框架的集成所预期的那样,React Testing Library 进行了清理以使测试不相互影响,afterEach
是正确的地方。正如 the documentation 所述,
Cleanup is called after each test automatically by default if the testing framework you're using supports the afterEach global (like mocha, Jest, and Jasmine).
编写测试的正确方法是在 RTL 清理之前等待组件内部的副作用完成。这需要在每个测试中等待至少与副作用持续时间(50 毫秒)相同的时间,并且需要更长的时间才能刷新承诺。 waitFor
的使用允许不依赖实现细节。由于副作用会影响测试结果,waitFor
的正确位置是 beforeEach
或测试本身,而不是 afterEach
或 afterAll
。
此外 await waitFor(() => render(<App />))
没有任何用处,因为它只对抛出错误的函数有效,最常见的是断言。可以简化为render(<App />)
.