Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recipe for funtion call verification within stream matchers #341

Open
raveesh-me opened this issue Feb 26, 2021 · 2 comments
Open

Recipe for funtion call verification within stream matchers #341

raveesh-me opened this issue Feb 26, 2021 · 2 comments

Comments

@raveesh-me
Copy link

raveesh-me commented Feb 26, 2021

Code that I want to test:

 final cachedResult = cacheBox.get(uri);
    if (cachedResult != null)
      controller.add(SWREvent(
        eventStatus: SWREventStatus.cacheResponse,
        data: cachedResult,
        swrMessage: 'returning the cached data first',
      ));

    /// make the network call
    final response = await this.getUri(uri,
        options: options,
        cancelToken: cancelToken,
        onReceiveProgress: onReceiveProgress);

    /// if our response is a failure, we should invalidate cache and
    /// return the error response
    if (response.statusCode != 200) {
      if (cachedResult != null) cacheBox.delete(uri);
      controller.add(SWREvent(
        eventStatus: SWREventStatus.error,
        data: response.data,
        dioResponse: response,
        swrMessage: response.statusMessage,
      ));
      controller.close();
      return;
    }

    /// if our cached data is up to date with remote, we should
    /// close the streamcontroller and return.
    if (cachedResult != null && response.data == cachedResult) {
      controller.close();
      return;
    }

    /// finally, we should update the cache anyways, and push the result to the
    /// stream and close the controller
    cacheBox.put(uri, response.data);
    controller.add(SWREvent(
        data: response.data,
        eventStatus: SWREventStatus.networkResponse,
        swrMessage: null));
    controller.close();
    return;

My test:

test('''WHEN mockbox returns null
    GET only networkResponse
    AND Box put method called''', () async {
      MockBox mockBox = MockBox();
      Stream sWRStream = Dio().getSWRUri(
        Uri.parse(REQUEST_URI),
        mockBox,
      );
      expect(
        sWRStream,
        emitsInOrder([
          isA<SWREvent>().having(
            (swrEvent) => swrEvent.eventStatus,
            'only network response is pushed',
            SWREventStatus.networkResponse,
          ),
          emitsDone,
        ]),
      );
    });
  });

Purpose

I want to verify whether the put() has been called in the stream, and can not find any example where I can add the verify method for this use case.

Preferred Solution

I would like to have something like this...

expect(
        sWRStream,
        emitsInOrder([
          isA<SWREvent>().having(
            (swrEvent) => swrEvent.eventStatus,
            'only network response is pushed',
            SWREventStatus.networkResponse,
          ),
          emitsDone.havingVerified(MockBox.put(any, any).called(1), 'put method was called on box once'),
        ]),
      );
@raveesh-me raveesh-me changed the title Recipe for stream verification Recipe for stream verification within stream matchers Feb 26, 2021
@raveesh-me raveesh-me changed the title Recipe for stream verification within stream matchers Recipe for funtion call verification within stream matchers Feb 26, 2021
@srawlins
Copy link
Member

Thanks for the question. I think I partially understand it :). FIrst, when you say "I want to verify whether the put() has been called in the stream," I'm a little lost. This is the first mention of a method called put. It's not in the Code you want to test, nor in the test.

Second, "has been called in the stream" is not a concept I'm comfortable with sticking to. A stream is just a sequence of objects, it is not a... sequence of actions or of method calls... I'll hazard a guess that you want to verify that, in the process of listening to the stream, and reading objects out of it, mockBox.put was called.

If this is the case, why not just use the standard verify API immediately after verifying the stream's contents with emitsInOrder? Are the Stream matchers asynchronous as well? I think expectLater may help here...

@raveesh-me
Copy link
Author

@srawlins thanks for the comment. :)

I want to verify that as a side effect, the local database, in this case hive, is receiving a write request, which is something I want to be sure about in this unit.

mockBox.put is Box.put from Hive, which is our local database for now.
I have also updated the reference code, I had initially missed including it there.

you are right about streams, I also want to stick to thinking of streams as a series of events. I just want to verify if whether a method for a side effect has been called from when the execution started to when the stream was closed.

problem with using the standard verify() is, that I can not await the expect() in with StreamMatcher. This means the verify will be executed before stream has closed.

I would be thankful if someone could show me how to put a verify inside an expectLater.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants