felangel / mocktail

A mock library for Dart inspired by mockito
https://pub.dev/packages/mocktail
MIT License
617 stars 81 forks source link

Invalid argument(s): An argument matcher (like `any()`) was either not used #104

Closed raxahai closed 5 months ago

raxahai commented 2 years ago

Getting error:

Invalid argument(s): An argument matcher (like any()) was either not used as an immediate argument to Symbol("get") (argument matchers can only be used as an argument for the very method being stubbed or verified), or was used as a named argument without the Mocktail "named" API (Each argument matcher that is used as a named argument needs to specify the name of the argument it is being used in. For example: when(() => obj.fn(x: any(named: "x")))).

class MockHttpClient extends Mock implements http.Client {}

void main() {
  late MockHttpClient mockHttpClient;
  late HomeRemoteDataSourceImplementation homeRemoteDataSourceImplementation;

  setUp(() {
    mockHttpClient = new MockHttpClient();
    homeRemoteDataSourceImplementation =
        new HomeRemoteDataSourceImplementation(client: mockHttpClient);
  });

  group("getMedicalRecords", () {
    test(("should perform a GET request on a URL with application/json header"),
        () {
      when(() => mockHttpClient.get(Uri.parse(any()),
          headers: any(named: "headers"))).thenAnswer(
        (_) async =>
            http.Response(fixtures("Home/fixtures/medical_record.json"), 200),
      );

      homeRemoteDataSourceImplementation.getMedicalRecord();

      verify(
        () => mockHttpClient.get(
          Uri.parse(
              "https://run.mocky.io/v3/30579b01-75f8-4c9f-ac83-c98b5cfe1d2e"),
          headers: {
            "Content-Type": "application/json",
          },
        ),
      );
    });
  });
}
mousedownmike commented 2 years ago

Your matchers on the mockHttpClient.get call are mixed. Replace Uri.parse(any()) with any() like so:

when(() => mockHttpClient.get(any(),
          headers: any(named: "headers"))).thenAnswer(
        (_) async =>
            http.Response(fixtures("Home/fixtures/medical_record.json"), 200),
raxahai commented 2 years ago

Did this as per your suggestion:

when(() => mockHttpClient.get(
            // Uri.parse(// cant use any as null exception
            //     "https://run.mocky.io/v3/30579b01-75f8-4c9f-ac83-c98b5cfe1d2e"),
            any(),
            headers: any(named: "headers"),
          )).thenAnswer(
        (_) async => http.Response(
            fixtures("features/Home/fixtures/medical_record.json"), 200),
      );

Bad state: A test tried to use any or captureAny on a parameter of type Uri, but registerFallbackValue was not previously called to register a fallback value for Uri.

To fix, do:

void main() {
  setUpAll(() {
    registerFallbackValue(/* create a dummy instance of `Uri` */);
  });
}
mousedownmike commented 2 years ago

Yes, you need a "Fake" Uri as described in the README. There's a good example in the bloc library weather example's meta_weather_api_client_test

To get it going you would want to add something like:

class FakeUri extends Fake implements Uri {}
void main() {
    setUpAll(() {
      registerFallbackValue(FakeUri());
    });

/* ... your tests ... */
}
n1h41 commented 2 years ago

Yes, you need a "Fake" Uri as described in the README. There's a good example in the bloc library weather example's meta_weather_api_client_test

To get it going you would want to add something like:

class FakeUri extends Fake implements Uri {}
void main() {
    setUpAll(() {
      registerFallbackValue(FakeUri());
    });

/* ... your tests ... */
}

Hey, how can I create a registerFallbackValue for an enum ?

felangel commented 2 years ago

Yes, you need a "Fake" Uri as described in the README. There's a good example in the bloc library weather example's meta_weather_api_client_test To get it going you would want to add something like:

class FakeUri extends Fake implements Uri {}
void main() {
    setUpAll(() {
      registerFallbackValue(FakeUri());
    });

/* ... your tests ... */
}

Hey, how can I create a registerFallbackValue for an enum ?

You can just pass any enum value, no need to create a fake.

n1h41 commented 2 years ago

Yes, you need a "Fake" Uri as described in the README. There's a good example in the bloc library weather example's meta_weather_api_client_test To get it going you would want to add something like:

class FakeUri extends Fake implements Uri {}
void main() {
    setUpAll(() {
      registerFallbackValue(FakeUri());
    });

/* ... your tests ... */
}

Hey, how can I create a registerFallbackValue for an enum ?

You can just pass any enum value, no need to create a fake.

Bad state: A test tried to useanyorcaptureAnyon a parameter of typeMETHOD, but registerFallbackValue was not previously called to register a fallback value forMETHOD`.

To fix, do:

void main() {
  setUpAll(() {
    registerFallbackValue(/* create a dummy instance of `METHOD` */);
  });
}

This instance of METHOD will only be passed around, but never be interacted with. Therefore, if METHOD is a function, it does not have to return a valid object and could throw unconditionally. If you cannot easily create an instance of METHOD, consider defining a Fake:

class MyTypeFake extends Fake implements MyType {}

void main() {
  setUpAll(() {
    registerFallbackValue(MyTypeFake());
  });
}

This is the error I am getting while trying to pass the enum value Note: the function I am trying to mock takes an argument of the enum type METHOD

felangel commented 2 years ago

@n1h41 can’t you provide a minimal reproduction sample?

n1h41 commented 2 years ago

@n1h41 can’t you provide a minimal reproduction sample?

as you mentioned before I passed the enum value without creating the fake. It's working. Thanks

raxahai commented 1 year ago
test("should fetch customer info", () async {
    // arrange
    when(() => mockDioClient.get(any())).thenAnswer(
      (_) async => Response(
        data: fixture("customer_fixture.json"),
        requestOptions: any(),
        statusCode: 200,
      ),
    );

    // act
    var result = await profileRemoteDataSourceImpl.getCustomerInfo();

    // assert
    expect(result, testCustomerModel);
    verify(() => mockDioClient.get(Urls.getCustomerInfo));
    verifyNoMoreInteractions(mockDioClient);
  });

Getting this error:

Invalid argument(s): The "any" argument matcher is used outside of method stubbing (via when) or verification (via verify or untilCalled). This is invalid, and results in bad behavior during the next stubbing or verification.

alestiago commented 1 year ago

@raxahai I see that you've re-opened the issue. Do you still have an error? If so, can you provide minimal reproductive code (without external package dependencies besides mocktail)? Else can the issue be closed?

djilet commented 8 months ago

it happens when i am using any() inside Record

felangel commented 5 months ago

Closing this for now since the issue is quite old and there aren't any actionable next steps. If anyone is still facing an issue please file a new bug and provide a minimal reproduction sample and I'm happy to take a closer look 👍