State notifier test - A testing library which makes it easy to test StateNotifier. Built to be used with the state notifier, riverpod or flutter riverpod packages

Overview

Package

Package is a port of felangel's bloc_test, modified to work with StateNotifier class

Installation

Add to dev dependencies inside pubspec_yaml:

    dev_dependencies:
        state_notifier_test: [version]

Usage

import 'package:state_notifier_test.dart';

stateNotifierTest(
  'CounterNotifier emits [10] when seeded with 9',
  build: () => CounterNotifier(),
  seed: () => 9,
  actions: (stateNotifier) => stateNotifier.increment(),
  expect: () => [10],
);

class CounterStateNotifier extends StateNotifier<int> {
  CounterStateNotifier() : super(0);

  void increment() {
    state = state + 1;
  }
}

stateNotifierTest can also be used to skip any number of emitted states before asserting against the expected states. skip defaults to 0.

stateNotifierTest(
  'CounterNotifier emits [2] when increment is called twice',
  build: () => CounterNotifier(),
  actions: (stateNotifier) {
    stateNotifier
      ..increment()
      ..increment();
  },
  skip: 1,
  expect: () => [2],
);

stateNotifierTest can also be used to verify internal stateNotifier functionality.

stateNotifierTest(
  'CounterNotifier emits [1] when increment is called',
  build: () => CounterNotifier(),
  actions: (stateNotifier) => stateNotifier.increment(),
  expect: () => [1],
  verify: (_) {
    verify(() => repository.someMethod(any())).called(1);
  }
);

Testing Options

setUp is optional and should be used to set up any dependencies prior to initializing the stateNotifier under test. setUp should be used to set up state necessary for a particular test case. For common set up code, prefer to use setUp from package:test/test.dart.

build should construct and return the stateNotifier under test.

seed is an optional Function that returns a state which will be used to seed the stateNotifier before actions is called.

actions is an optional callback which will be invoked with the stateNotifier under test and should be used to interactions with the stateNotifier.

skip is an optional int which can be used to skip any number of states. skip defaults to 0.

expect is an optional Function that returns a Matcher which the stateNotifier under test is expected to emit after actions is executed.

verify is an optional callback which is invoked after expect and can be used for additional verification/assertions. verify is called with the stateNotifier returned by build.

errors is an optional Function that returns a Matcher which the stateNotifier under test is expected to throw after actions is executed.

tearDown is optional and can be used to execute any code after the test has run. tearDown should be used to clean up after a particular test case. For common tear down code, prefer to use tearDown from package:test/test.dart.

You might also like...

Flutter Youtube Redesign. this gave me so much Experience For Flutter . I used Video_player and Spring animation packages in this project

youtube A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if this

Dec 13, 2021

MoneyTextFormField is one of the flutter widget packages that can be used to input values in the form of currencies, by displaying the output format in realtime.

MoneyTextFormField is one of the flutter widget packages that can be used to input values in the form of currencies, by displaying the output format in realtime.

MoneyTextFormField MoneyTextFormField is one of the flutter widget packages that can be used to input values in the form of currencies, by displaying

Jan 1, 2023

This library provides a customizable Flutter widget that makes it easy to display text in the middle of a Divider.

This library provides a customizable Flutter widget that makes it easy to display text in the middle of a Divider.

1. About 1.1. Introduction 1.1.1. Install Library 1.1.2. Import It 1.1.3. Use TextDivider 1.2. Details 1.2.1. Customization Options 1.2.2. Horizontal

Feb 9, 2022

A library that makes it easy for you to create your own custom wizard.

A library that makes it easy for you to create your own custom wizard.

Flutter Wizard Author: Jop Middelkamp A library that makes it easy for you to create your custom wizard. You'll have 100% control over the appearance

Dec 2, 2022

An extension to the bloc state management library which lets you create State Machine using a declarative API

An extension to the bloc state management library which lets you create State Machine using a declarative API

Nov 28, 2022

State Persistence - Persist state across app launches. By default this library store state as a local JSON file called `data.json` in the applications data directory. Maintainer: @slightfoot

State Persistence Persist state across app launches. By default this library store state as a local JSON file called data.json in the applications dat

Sep 28, 2022

Riverpod Messages Listener: A message notification listener for apps build with Riverpod

Riverpod Messages Listener: A message notification listener for apps build with Riverpod

Riverpod Messages Listener Hello all, this is the home page of riverpod_messages package, a message notification listener for apps build with Riverpod

Dec 8, 2022

Bilgi Testi Flutter - A knowledge testing app built with Flutter

Bilgi Testi Flutter - A knowledge testing app built with Flutter

Bilgi Testi 7 sorudan oluşan puanlama mekaniği olan, modern tasarımlı, flutter i

Feb 9, 2022
Comments
  • Added ignoreBuildCalls parameter to be able to ignore build method's additional method calls

    Added ignoreBuildCalls parameter to be able to ignore build method's additional method calls

    If the StateNotifier's constructor calls some method that will update the state it will interfere with the method being called directly in the actions callback of the test itself.

    For example if in the StateNotifier we have a constructor and method we would like to test like below:

    class ExampleStateNotifier extends StateNotifier<ExampleState> {
      final ExampleRepository _recipeRepository;
      ExampleStateNotifier(this._exampleRepository)
          : super(const ExampleState.initial()) {
        loadExampleString();
      }
    
      Future<void> loadExampleString() async {
        state = const ExampleState.loading();
        final result = await _exampleRepository.loadExampleString();
        state = result.fold(
            (failure) => ExampleState.error(error: failure.failureMessage()),
            (data) => ExampleState.loaded(string: data.string ?? ''));
      }
    }
    

    Now if we want in the test to test loadExampleString() method, because loadExampleString() is also being called from the constructor we won't get expected states in the test, ExampleState.loading() and ExampleState.loaded(string: string). By adding a short delay after build() method is called in the testNotifier() method, loadExampleString() call from the constructor will be ignored and then when testing loadExampleString() we will be able to get the exact states we are expecting.

    The proposed solution then is to add new attribute ignoreBuildCalls when instantiating stateNotifierTest class and adding a short delay (100 ms should be enough for testing with mock repository) after the build() method is being called.

    If you see a different and perhaps better solution for the described problem, feel free to share it :)

    Other similar solution that comes to my mind is to introduce just afterBuild optional Future callback that could be await executed after the build() call to maybe have a little bit more options in defining how long this delay should be. On the other hand ignoreBuildCalls attribute is maybe more clear how to use it but I would also like to hear your opinion on that.

    Kind regards, Ivan Celija

    opened by icelija 4
  • Except is not an optional Function, and cannot take a TypeMatcher comparison (isA<>())

    Except is not an optional Function, and cannot take a TypeMatcher comparison (isA<>())

    Hi there! I run in a little problem while trying to create a test for my UserNotifier (StateNotifier).

    This is the constructor of stateNotifierTest:

    void stateNotifierTest<SN extends StateNotifier<State>, State>(
      String description, {
      required FutureOr Function(SN stateNotifier) actions,
      FutureOr<void> Function()? setUp,
      FutureOr<void> Function(SN stateNotifier)? verify,
      FutureOr<void> Function()? tearDown,
      required List<State> Function() expect,
      Iterable<State> Function()? seed,
      int skip = 0,
      required SN Function() build,
      dynamic Function()? errors,
      bool expectInitialState = false,
    }) { ...
    

    You mentioned in the comment above that we can use expect with isA<>() type matcher, but it is not possible with the current constructor declaration.

    /// **Note:** when using [stateNotifierTest] with state classes which don't override
    /// `==` and `hashCode` you can provide an `Iterable` of matchers instead of
    /// explicit state instances.
    ///
    /// ```dart
    /// stateNotifierTest(
    ///  'emits [StateB] when EventB is called',
    ///  build: () => MyBloc(),
    ///  action: (stateNotifier) => stateNotifier.add(EventB()),
    ///  expect: () => [isA<StateB>()],
    /// );
    /// ```
    

    So while trying to start the test like this:

    stateNotifierTest<UserNotifier, AsyncValue<User?>>(
      'returns error when trying to edit a null user',
      expectInitialState: false,
      build: () => UserNotifier(
        userId: null,
        userRepository: mockUserRepository,
      ),
      actions: (un) {
        un.editUser(user1);
      },
      expect: () => [isA<AsyncError>()],
    );
    

    I get this error Screenshot 2022-12-10 alle 13 16 23

    Removing the type doesn't work either. Screenshot 2022-12-10 alle 13 17 23

    I think being able to pass isA<>()would be very useful, since I have the editUser method that returns an AsyncValue.error, which requires the error object and also the current StackTrace, which is impossible to recreate as an object. I saw that there is an errors parameter, but still, since expect is required and must match exactly the test will fail.

    Thank you!

    opened by Ivaskuu 0
  • Stub with mocktail

    Stub with mocktail

    I'm trying to port the counter bloc example test link to Riverpod and the tests, bloc_test uses MockBloc/MockCubit to achieve this like this:

    class MockCounterCubit extends MockCubit<int> implements CounterCubit {}
    void main() {
    late CounterCubit counterCubit;
    
      setUp(() {
        counterCubit = MockCounterCubit();
      });
    
    testWidgets('renders current CounterCubit state', (tester) async {
          when(() => counterCubit.state).thenReturn(42);
          await tester.pumpWidget(
            MaterialApp(
              home: BlocProvider.value(
                value: counterCubit,
                child: CounterView(),
              ),
            ),
          );
          expect(find.text('42'), findsOneWidget);
        });
    }
    

    What I got is this:

    class CounterProvider extends StateNotifier<int> {
      CounterProvider() : super(0);
    
      void increment() => state = state + 1;
    
      void decrement() => state = state - 1;
    }
    
    class MockCounterStateNotifier extends Mock implements CounterProvider {}
    void main() {
      late CounterProvider counterProvider;
    
      setUp(() {
        counterProvider = MockCounterStateNotifier();
      });
    
      group('CounterView', () {
        testWidgets('renders current Counter state', (tester) async {
          //when(() => counterProvider.state).thenReturn(42);
          await tester.pumpWidget(
            const ProviderScope(
              child: MaterialApp(home: CounterPage()),
            ),
          );
          expect(find.text('42'), findsOneWidget);
        });
      });
    }
    
    opened by gengiscb 1
Owner
null
Custom flutter testing CLI tool for individual test runs and group testing

fluttertest Custom flutter testing CLI tool for inidividual test runs or group testing Overview Flutter is a great framework which has helps developer

vi_mi 15 Nov 6, 2022
A Flutter tool that makes golden testing easy.

???? Alchemist Developed with ?? by Very Good Ventures ?? and Betterment ☀️ . A Flutter tool that makes golden testing easy. Alchemist is a Flutter pa

Betterment 210 Dec 12, 2022
Simple and complete Flutter hooks testing utilities that encourage good testing practices.

Flutter Hooks Testing Library Simple and complete Flutter hooks testing utilities that encourage good testing practices. Inspired by react-hooks-testi

Daichi Furiya 24 Dec 2, 2022
Nexus is a state management library that makes it easy to create and consume your application's reactive data to the user interface.

Nexus ?? Nexus is a state management library that makes it easy to create and consume your application's reactive data to the user interface. With nex

Gor Mkhitaryan 3 Sep 7, 2022
Connection Notifier - A simple way to notify your user about the connection status.

Connection Notifier A simple way to notify your user about the connection status. Basic Usage: ConnectionNotifier class MyApp extends StatelessWidget

haptome 0 Apr 30, 2022
The Integration Test Helper has pre-configured methods that allow for faster test deployment for end to end (e2e) test coverage.

The Integration Test Helper has pre-configured methods that allow for faster test deployment for end to end (e2e) test coverage (using Android and iOS

The Mobile Applications Community 2 Apr 7, 2022
A test driver for Flutter to do QA testing without sharing app source code.

Autopilot A test driver for Flutter to do QA testing without sharing app source code. It exposes a JSON API using an HTTP server running inside the ap

Ajin Asokan 70 Dec 30, 2022
A simple test testing swagger_dart_code_generator 2.2.5+1

m_work_swagger_test_2 A simple test testing swagger_dart_code_generator 2.2.5+1 Was created like this: Create an ordinary Flutter project in AS2020.3.

Roar Grønmo 0 Nov 15, 2021
Value listenable test - Assists in testing ValueListenable objects (ex: ValueNotifier).

value_listenable_test Assists in testing ValueListenable objects (ex: ValueNotifier). install Added in your pubspec.yaml as dev dependency: dev_depend

Flutterando 3 Feb 23, 2022
Dart package to which makes data communication easy among different modules of your application.

LiveStream - Dart LiveStream is a data holder class which can observe change of data in real-time and emit values too. Here's emitter subscriber patte

Shreyas Patil 75 Sep 28, 2022