【问题标题】:How to implement widget tests by using mock cubit?如何使用 mock cubit 实现小部件测试?
【发布时间】:2021-12-21 03:19:33
【问题描述】:

我试图按照这个question 的答案,但我无法让它工作。

我在柜台应用上重现了我的问题,如下更改。

main.dart

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider(
          create: (BuildContext ctx) => DummyCubit(),
        ),
      ],
      child: MaterialApp(
      ...
}

class _MyHomePageState extends State<MyHomePage> {
  ...
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      ...
      body: Center(
        child: CounterViewer(counter: _counter),
      ),
      ...
    );
  }
}

class CounterViewer extends StatelessWidget {
  const CounterViewer({required this.counter, Key? key}) : super(key: key);

  final int counter;

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<DummyCubit, AState>(
      builder: (ctx, state) => (state is! StateLoaded)
          ? const CircularProgressIndicator()
          : Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$counter',
                  style: Theme.of(context).textTheme.headline4,
                ),
              ],
            ),
    );
  }
}

dummy_cubit.dart

import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';

class DummyCubit extends Cubit<AState> {
  DummyCubit() : super(const InitState());

  Future<void> executeLogic() async {
    emit(const StateLoading());
    // do some logic
    emit(StateLoaded('some data'));
  }
}

@immutable
abstract class AState {
  const AState();
}

class InitState extends AState {
  const InitState();
}

class StateLoading extends AState {
  const StateLoading();
}

class StateLoaded extends AState {
  const StateLoaded(this.data);

  final String data;

  @override
  String toString() => data.toString();

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      (other is StateLoaded &&
          runtimeType == other.runtimeType &&
          data == other.data);

  @override
  int get hashCode => data.hashCode;
}

widget_test.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:bloc_test/bloc_test.dart';
import 'package:mocktail/mocktail.dart' as mocktail;

import 'package:counter/dummy_cubit.dart';
import 'package:counter/main.dart';

class MockDummyCubit extends MockCubit<AState> implements DummyCubit {}

class AStateFake extends Fake implements AState {}

final dummyCubit = MockDummyCubit();

Widget get counter => MultiBlocProvider(
      providers: [
        BlocProvider<DummyCubit>(
          create: (BuildContext ctx) => dummyCubit,
        ),
      ],
      child: const MaterialApp(
        home: CounterViewer(counter: 1),
      ),
    );

void main() {
  setUpAll(() {
    mocktail.registerFallbackValue(AStateFake());
  });

  group('Counter viewer', () {
    mocktail.when(() => dummyCubit.state).thenReturn(InitState());
    testWidgets('should build', (WidgetTester tester) async {
      await tester.pumpWidget(counter);
    });
  });
}

运行测试时,我收到此错误:

The following StateError was thrown running a test:
Bad state: No method stub was called from within `when()`. Was a real method called, or perhaps an
extension method?

并删除 mocktail.when 行,我收到此错误:

The following _TypeError was thrown building CounterViewer:
type 'Null' is not a subtype of type 'AState'

我该如何解决这个问题?

如何控制 DummyCubit 发出的状态?

【问题讨论】:

    标签: flutter testing mocking bloc cubit


    【解决方案1】:

    看了this,找到了解决办法

    class MockDummyCubit extends MockCubit<AState> implements DummyCubit {}
    
    class AStateFake extends Fake implements AState {}
    
    void main() {
      late MockDummyCubit dummyCubit;
    
      setUpAll(() {
        mocktail.registerFallbackValue(AStateFake());
      });
    
      setUp(() {
        dummyCubit = MockDummyCubit();
        mocktail.when(() => dummyCubit.state).thenReturn(const InitState());
      });
    
      group('Counter viewer', () {
        testWidgets('should build', (WidgetTester tester) async {
          await tester.pumpWidget(getCounter(dummyCubit));
        });
      });
    }
    
    Widget getCounter(MockDummyCubit dummyCubit) => MultiBlocProvider(
          providers: [
            BlocProvider<DummyCubit>(
              create: (BuildContext ctx) => dummyCubit,
            ),
          ],
          child: const MaterialApp(
            home: CounterViewer(counter: 1),
          ),
        );
    

    【讨论】:

      猜你喜欢
      • 2021-07-11
      • 2019-12-27
      • 1970-01-01
      • 2016-02-22
      • 2012-10-24
      • 2014-07-05
      • 2016-04-29
      • 2021-01-21
      • 1970-01-01
      相关资源
      最近更新 更多