olexale / bdd_widget_test

A BDD-style widget testing library
MIT License
101 stars 30 forks source link

Pattern for per-scenario state? #3

Closed kentcb closed 4 years ago

kentcb commented 4 years ago

Hi,

Is there any support for passing state through a feature/scenario? I have abstracted all integration with the real world into APIs and have mocks of those APIs, but it's unclear how to best:

  1. Create an instance of those mocks when a scenario starts. I can do this easily enough as a step, but what does the step then do with the created mocks?
  2. Pass the mocks through the various steps in the scenario.

My only choice seems to be using a global variable for the mocks, which makes me somewhat uneasy.

olexale commented 4 years ago

Hi Kent,

In my projects I use get_it with injectable. For tests I create a separate environment with injectable, which contains all services of the app, and replace all external 3rd-party dependencies (database, networking, analytics, etc) with mocks. During the initialization of the scenario I’m setting up these mocks, i.e. I have steps like “And the BE responds with an empty list” which I find intuitive and easy to read for non-technical folks in the team.

Here is a sample repository with this approach, and here is a video with some explanations.

Hope that helps!

kentcb commented 4 years ago

Thanks for the quick response. That's actually very similar to what I ended up doing, so glad I'm on the right track!

CodingSoot commented 2 years ago

Hello, Is there any way to use riverpod instead of get_it for passing state through a scenario ?

olexale commented 2 years ago

Hey, The package does not rely on get_it, you may use riverpod or any other package. What exactly you are trying to achieve?

CodingSoot commented 2 years ago

Here is a sample repository with this approach, and here is a video with some explanations.

In this example, you use get_it to access the mocked IAuthFacade and mock a response of the BE:

Future<void> theBeWillRejectAnyCredentials(WidgetTester tester) async {
  final auth = getIt<IAuthFacade>();
  when(auth.signInWithEmailAndPassword(
          emailAddress: anyNamed('emailAddress'),
          password: anyNamed('password')))
      .thenAnswer(
    (realInvocation) => Future.value(
      left(
        const AuthFailure.invalidEmailAndPasswordCombination(),
      ),
    ),
  );
}

When using Riverpod, we need the ref to access providers:

Future<void> theBeWillRejectAnyCredentials(WidgetTester tester) async {
   final auth = ref.read(authProvider);
  //...
}

But there's no way to have a ref inside the step.

olexale commented 2 years ago

https://stackoverflow.com/a/72472306/1010710