riverpod-testing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Riverpod — Testing

Riverpod — 测试

Instructions

说明

Riverpod is designed for testability: isolate state per test, mock via overrides, and keep the test environment close to production.
Riverpod专为可测试性设计:在每个测试中隔离状态、通过重写实现模拟,确保测试环境与生产环境高度接近。

Unit tests (no Flutter)

单元测试(无Flutter)

Use ProviderContainer.test() to create a container for the test. Do not share containers between tests.
dart
void main() {
  test('Some description', () {
    final container = ProviderContainer.test();
    expect(container.read(provider), equals('some value'));
  });
}
  • container.read(provider) — Read current value.
  • container.listen(provider, (prev, next) {}) — Listen and get a subscription; use subscription.read() to read. Prefer listen when the provider is auto-dispose so it is not disposed mid-test.
dart
final subscription = container.listen<String>(provider, (_, _) {});
expect(subscription.read(), 'Some value');
使用**ProviderContainer.test()**为测试创建容器。不要在测试之间共享容器。
dart
void main() {
  test('Some description', () {
    final container = ProviderContainer.test();
    expect(container.read(provider), equals('some value'));
  });
}
  • container.read(provider) — 读取当前值。
  • container.listen(provider, (prev, next) {}) — 监听并获取订阅;使用**subscription.read()**读取值。当提供者为自动销毁类型时,优先使用listen,避免测试中途提供者被销毁。
dart
final subscription = container.listen<String>(provider, (_, _) {});
expect(subscription.read(), 'Some value');

Widget tests

组件测试

Wrap the widget under test in ProviderScope:
dart
testWidgets('Some description', (tester) async {
  await tester.pumpWidget(
    const ProviderScope(child: YourWidgetYouWantToTest()),
  );
});
To interact with providers in the test, get the container with tester.container():
dart
final container = tester.container();
expect(container.read(provider), 'some value');
将待测试组件包裹在ProviderScope中:
dart
testWidgets('Some description', (tester) async {
  await tester.pumpWidget(
    const ProviderScope(child: YourWidgetYouWantToTest()),
  );
});
要在测试中与提供者交互,使用**tester.container()**获取容器:
dart
final container = tester.container();
expect(container.read(provider), 'some value');

Mocking providers

模拟提供者

Use overrides on ProviderContainer or ProviderScope. All providers can be overridden without extra setup.
dart
final container = ProviderContainer.test(
  overrides: [
    exampleProvider.overrideWith((ref) => 'Hello from tests'),
  ],
);

// Or in widget tests:
await tester.pumpWidget(
  ProviderScope(
    overrides: [exampleProvider.overrideWith((ref) => 'Hello from tests')],
    child: const YourWidgetYouWantToTest(),
  ),
);
See riverpod-overrides for family overrides and other override methods.
在ProviderContainer或ProviderScope上使用overrides。所有提供者无需额外配置即可被重写。
dart
final container = ProviderContainer.test(
  overrides: [
    exampleProvider.overrideWith((ref) => 'Hello from tests'),
  ],
);

// 或在组件测试中:
await tester.pumpWidget(
  ProviderScope(
    overrides: [exampleProvider.overrideWith((ref) => 'Hello from tests')],
    child: const YourWidgetYouWantToTest(),
  ),
);
如需了解family重写及其他重写方法,请查看riverpod-overrides。

Awaiting async providers

等待异步提供者

Read provider.future to get a Future that completes with the provider value; use with expectLater:
dart
await expectLater(
  container.read(provider.future),
  completion('some value'),
);
读取provider.future以获取一个Future,该Future会在提供者值就绪时完成;可与expectLater配合使用:
dart
await expectLater(
  container.read(provider.future),
  completion('some value'),
);

Listening / spying

监听/监视

Use container.listen(provider, callback) and assert on the callback arguments or collect values in a list for assertions. Works with mockito/mocktail verify patterns.
使用container.listen(provider, callback),并对回调参数进行断言,或收集值到列表中用于断言。此方法可与mockito/mocktail的verify模式配合使用。

Mocking Notifiers

模拟Notifier

Prefer mocking a dependency (e.g. repository) the Notifier uses rather than mocking the Notifier. If you must mock a Notifier, subclass it (do not implement), so the mock extends the original base class. With code generation, the mock usually needs to live in the same file as the Notifier to access the generated base class.
See riverpod-overrides and the official docs for more examples.
优先模拟Notifier所依赖的对象(例如仓库),而非直接模拟Notifier。如果必须模拟Notifier,请继承它(不要实现接口),这样模拟类会继承原始基类。若使用代码生成,模拟类通常需要与Notifier位于同一文件中,以访问生成的基类。
更多示例请查看riverpod-overrides及官方文档。