Giter Club home page Giter Club logo

Comments (16)

theiskaa avatar theiskaa commented on May 27, 2024 6

Hi @tazik561 !

The problem is you're throwing a AdapterError as expected value:

expect(() async => await dio.post(path), throwsA(isA<AdapterError>()));

But you was given a DioError into dioAdapterMockito.onPost method:

  dioAdapterMockito.onPost(
        path,
        (request) => request.throws(500, dioError),
        headers: {'Content-Type': 'application/json; charset=utf-8'},
      );

So I mean you should change your expected value as DioError, like:

  expect(() async => await dio.post(path), throwsA(isA< DioError>()));

The full test code:
Note: I am using the latest version of the packages

void main() {
  group("Splash init", () {
    DioAdapterMockito dioAdapterMockito;
    Dio dio;
    const path = 'https://..../mobile/';

    setUpAll(() {
      dioAdapterMockito = DioAdapterMockito();
      dio = Dio()..httpClientAdapter = dioAdapterMockito;
    });

    test(
        "call getMainConfigs -> getMainConfig web service called 404 exception",
        () async {
      final dioError = DioError(
        error: {'message': 'Some beautiful error!'},
        requestOptions: RequestOptions(path: path),
        response: Response(
          statusCode: 500,
          requestOptions: RequestOptions(path: path),
        ),
        type: DioErrorType.response,
      );

      dioAdapterMockito.onPost(
        path,
        (request) => request.throws(500, dioError),
        headers: {'Content-Type': 'application/json; charset=utf-8'},
      );
      expect(() async => await dio.post(path), throwsA(isA<AdapterError>()));
      // expect(() async => await dio.get(path), throwsA(isA<DioError>()));
      // expect(
      //   () async => await dio.get(path),
      //   throwsA(
      //     predicate(
      //       (DioError error) =>
      //           error is DioError &&
      //           error is AdapterError &&
      //           error.message == dioError.error.toString(),
      //     ),
      //   ),
      // );
    });
  });
}

Correct and clean usage of http-mock-adapter should be:

void main() {
  DioAdapter dioAdapterMockito;
  Dio dio;

  DioError dioError;

  const path = 'https://example.com';

  setUpAll(() {
    dioAdapterMockito = DioAdapterMockito();
    dio = Dio();

    dio.httpClientAdapter = dioAdapterMockito;

    DioError(
      error: {'message': 'Some beautiful error!'},
      requestOptions: RequestOptions(path: path),
      response: Response(
        statusCode: 500,
        requestOptions: RequestOptions(path: path),
      ),
      type: DioErrorType.response,
    );
  });
  group("Splash init", () {
    test(
        "call getMainConfigs -> getMainConfig web service called 404 exception",
        () async {
      dioAdapterMockito.onPost(
        path,
        (request) => request.throws(500, dioError),
        headers: {'Content-Type': 'application/json; charset=utf-8'},
      );

      expect(() async => await dio.post(path), throwsA(isA<DioError>()));
    });
  });
}

from http-mock-adapter.

LukaGiorgadze avatar LukaGiorgadze commented on May 27, 2024 3

@tazik561 are you using the latest version of http_mock_adapter?

from http-mock-adapter.

theiskaa avatar theiskaa commented on May 27, 2024 2

@LukaGiorgadze no Luka, we were resolved this issue with #100 PR. @tazik561 's issue needn't any changes on http-mock-adapter, he just should do this , so the problem is his test code.

from http-mock-adapter.

tazik561 avatar tazik561 commented on May 27, 2024 2

Hi @tazik561
I tried fix your problem by initializing dio: ^3.0.9 and http_mock_adapter: ^0.1.6.
And I fixed it, It's simple you just need to change your expected value to:

expect(() async => await dio.post(path), throwsA(isA<DioError>()));

Just that, and I said that in this answer.

I don't want to test dio directly . As I mention above I have a method called : getConcreteNumberTrivia.

  Future<NumberTriviaModel> getConcreteNumberTrivia(String url) async {
    final response =
        await dio.get(url, headers: {'Content-Type': 'application/json'});

    if (response.statusCode == 200) {
      return NumberTriviaModel.fromJson(json.decode(response.body));
    } else {
      throw ServerExceptions();
    }
  }

I am trying write test for this method getConcreteNumberTrivia. Inside this method there is a dio .Now I want when parser rich to dio, dio throw an error or exception .

In this answer we just test dio directly. But I want to test a method that has dio part like repository layer.

for example

setupMockHttpClientFailure404(){
      dioAdapterMockito.onPost(
        path,
        (request) => request.throws(404, dioError),
        headers: {'Content-Type': 'application/json; charset=utf-8'},
      );
}
    test(
      'should throw a ServerException when the responce code is 404 or other ',
      () async {
        setupMockHttpClientFailure404();
        final call = dataSource.getConcreteNumberTrivia;
        expect(call(url), throwsA(TypeMatcher<ServerExceptions>()));
      },
    );

I call final call = dataSource.getConcreteNumberTrivia; in test, In getConcreteNumberTrivia method when parser rich to final response = await dio.get(url, headers: {'Content-Type': 'application/json'}); , throw an exception.

from http-mock-adapter.

erayerdin avatar erayerdin commented on May 27, 2024 2

Well, I'm trying to use this with get_it. I register my client with:

getIt.registerLazySingleton(
      () => BaseOptions(baseUrl: 'https://www.bscotch.net/api/levelhead'),
      instanceName: 'rumpusClientBaseOptions');
  getIt.registerLazySingleton(
      () => Dio(getIt.get(instanceName: 'rumpusClientBaseOptions')),
      instanceName: 'rumpusClient');

Then in setUpAll, I do:

setUpAll(() async {
      await setUpDI();

      var adapter = DioAdapter();
      adapter
        ..onGet(
            '/players',
            (request) => request.reply(200, {
                  'data': [
                    {
                      "_id": "609e5516f0b9d200b711b8b5",
                      "userId": "pvdw78",
                      "stats": {
                        "Subscribers": 0,
                        "NumFollowing": 0,
                        "Crowns": 0,
                        "Shoes": 0,
                        "PlayTime": 0,
                        "TipsPerLevel": 0,
                        "TipsPerDay": 0,
                        "TippedPerLevelPlayed": 0,
                        "TippedPerDay": 0,
                        "HiddenGem": 0,
                        "Trophies": 0,
                        "PerkPoints": 5,
                        "CampaignProg": 0,
                        "TimeTrophies": 0
                      },
                      "createdAt": "2021-05-14T10:46:46.723Z",
                      "updatedAt": "2021-05-14T10:46:48.639Z",
                      "alias": {
                        "userId": "pvdw78",
                        "alias": "LeapyimbleZiprompa",
                        "avatarId": "gr18-serious",
                        "context": "levelhead"
                      }
                    }
                  ]
                }));
      Dio client = getIt.get(instanceName: 'rumpusClient');
      client.httpClientAdapter = adapter;
    });

Since it is a lazy singleton, I'm sure I get the only one instance of Dio. I change the adapter to this mock adapter as you can see above. However, running my tests, I get the error saying:

DioError [DioErrorType.other]: Assertion failed: "Could not find mocked route matching request for /players/GET/null/{includeRecords: true, includeStats: true, userIds: foobar}/{}"

Opting out of baseUrl also does no good.


Environment

 > flutter --version
Flutter 2.0.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision adc687823a (4 weeks ago) • 2021-04-16 09:40:20 -0700
Engine • revision b09f014e96
Tools • Dart 2.12.3
  • dio 4.0.0
  • http_mock_adapter 0.2.1

from http-mock-adapter.

kuhnroyal avatar kuhnroyal commented on May 27, 2024 2

I have had several cases where the mocked route could not be found. It was always my mistake but it is hard to trace down with the current assertion errors. I suggest we introduce a custom error messages with diffs for data/headers/params, especially if there is only one mocked response. With more than one mocked response it might get a bit harder to generate a correct diff.

from http-mock-adapter.

tazik561 avatar tazik561 commented on May 27, 2024 1

Hi @tazik561 !

The problem is you're throwing a AdapterError as expected value:

expect(() async => await dio.post(path), throwsA(isA<AdapterError>()));

But you was given a DioError into dioAdapterMockito.onPost method:

  dioAdapterMockito.onPost(
        path,
        (request) => request.throws(500, dioError),
        headers: {'Content-Type': 'application/json; charset=utf-8'},
      );

So I mean you should change your expected value as DioError, like:

  expect(() async => await dio.post(path), throwsA(isA<AdapterError>()));

The full test code:
Note: I am using the latest version of the packages

void main() {
  group("Splash init", () {
    DioAdapterMockito dioAdapterMockito;
    Dio dio;
    const path = 'https://..../mobile/';

    setUpAll(() {
      dioAdapterMockito = DioAdapterMockito();
      dio = Dio()..httpClientAdapter = dioAdapterMockito;
    });

    test(
        "call getMainConfigs -> getMainConfig web service called 404 exception",
        () async {
      final dioError = DioError(
        error: {'message': 'Some beautiful error!'},
        requestOptions: RequestOptions(path: path),
        response: Response(
          statusCode: 500,
          requestOptions: RequestOptions(path: path),
        ),
        type: DioErrorType.response,
      );

      dioAdapterMockito.onPost(
        path,
        (request) => request.throws(500, dioError),
        headers: {'Content-Type': 'application/json; charset=utf-8'},
      );
      expect(() async => await dio.post(path), throwsA(isA<AdapterError>()));
      // expect(() async => await dio.get(path), throwsA(isA<DioError>()));
      // expect(
      //   () async => await dio.get(path),
      //   throwsA(
      //     predicate(
      //       (DioError error) =>
      //           error is DioError &&
      //           error is AdapterError &&
      //           error.message == dioError.error.toString(),
      //     ),
      //   ),
      // );
    });
  });
}

Correct and clean use of http-mock-adapter should be:

void main() {
  DioAdapter dioAdapterMockito;
  Dio dio;

  DioError dioError;

  const path = 'https://example.com';

  setUpAll(() {
    dioAdapterMockito = DioAdapterMockito();
    dio = Dio();

    dio.httpClientAdapter = dioAdapterMockito;

    DioError(
      error: {'message': 'Some beautiful error!'},
      requestOptions: RequestOptions(path: path),
      response: Response(
        statusCode: 500,
        requestOptions: RequestOptions(path: path),
      ),
      type: DioErrorType.response,
    );
  });
  group("Splash init", () {
    test(
        "call getMainConfigs -> getMainConfig web service called 404 exception",
        () async {
      dioAdapterMockito.onPost(
        path,
        (request) => request.throws(500, dioError),
        headers: {'Content-Type': 'application/json; charset=utf-8'},
      );

      expect(() async => await dio.post(path), throwsA(isA<DioError>()));
    });
  });
}

Thank . I changed my code to this:

  group("Dio Exception", () {
    DioAdapterMockito dioAdapterMockito;
    Dio dio;
    DioError dioError;
     const path = 'https://..../mobile/';

    setUpAll(() {
      dioAdapterMockito = DioAdapterMockito();
      dio = Dio()..httpClientAdapter = dioAdapterMockito;

      dioError = DioError(
        error: {'message': 'Some beautiful error!'},
        request: RequestOptions(
          path: path,
        ),
        response: Response(
          statusCode: 500,
          request: RequestOptions(path: path),
        ),
        type: DioErrorType.RESPONSE,
      );
    });
    test(
        "call getMainConfigs -> getMainConfig web service called 404 exception",
        () async {
      dioAdapterMockito.onPost(
        path,
        (request) => request.throws(500, dioError),
        headers: {'Content-Type': 'application/json; charset=utf-8'},
      );

      var result = await dio.post(path, data: null);
      expect(() async => result, throwsA(isA<DioError>()));
    });
  });
}

But I got this error:

DioError [DioErrorType.DEFAULT]: NoSuchMethodError: The getter 'headers' was called on null.
Receiver: null
Tried calling: headers
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1      DioMixin._dispatchRequest
package:dio/src/dio.dart:927
<asynchronous suspension>
#2      StackZoneSpecification._registerUnaryCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart)
package:stack_trace/src/stack_zone_specification.dart:1
<asynchronous suspension>
2

DioMixin._dispatchRequest
package:dio/src/dio.dart:966

from http-mock-adapter.

theiskaa avatar theiskaa commented on May 27, 2024 1

@tazik561

Don't create a variable for await dio.post() just write it directly.
However expect method should be:

expect(() async => await dio.post(path, data: null),
          throwsA(isA<DioError>()));

Not this:

var result = await dio.post(path, data: null);
expect(() async => result, throwsA(isA<DioError>()));

And make sure you're using latest versions of dio and http_mock_adapter.

Here is the full code of your test:

group("Dio Exception", () {
    DioAdapterMockito dioAdapterMockito;
    Dio dio;
    DioError dioError;
    const path = 'https://..../mobile/';

    setUpAll(() {
      dioAdapterMockito = DioAdapterMockito();
      dio = Dio()..httpClientAdapter = dioAdapterMockito;

      dioError = DioError(
        error: {'message': 'Some beautiful error!'},
        requestOptions: RequestOptions(path: path),
        response: Response(
          statusCode: 500,
          requestOptions: RequestOptions(path: path),
        ),
        type: DioErrorType.response,
      );
    });
    test(
        "call getMainConfigs -> getMainConfig web service called 404 exception",
        () async {
      dioAdapterMockito.onPost(
        path,
        (request) => request.throws(500, dioError),
        headers: {'Content-Type': 'application/json; charset=utf-8'},
      );

      expect(() async => await dio.post(path, data: null),
          throwsA(isA<DioError>()));
    });
  });

from http-mock-adapter.

tazik561 avatar tazik561 commented on May 27, 2024 1

Of course not. I am using dio: ^3.0.9 and http_mock_adapter: ^0.1.6 because I don't use sounds null safety environment: sdk: ">=2.7.0 <3.0.0".

It is possible to mix DioAdapterMockito in this way ):

setupMockHttpClientFailure404(){
      dioAdapterMockito.onPost(
        path,
        (request) => request.throws(404, dioError),
        headers: {'Content-Type': 'application/json; charset=utf-8'},
      );
}
    test(
      'should throw a ServerException when the responce code is 404 or other ',
      () async {
        setupMockHttpClientFailure404();
        final call = dataSource.getConcreteNumberTrivia;
        expect(call(url), throwsA(TypeMatcher<ServerExceptions>()));
      },
    );

main method on repo class:

  Future<NumberTriviaModel> getConcreteNumberTrivia(String url) async {
    final response =
        await dio.get(url, headers: {'Content-Type': 'application/json'});

    if (response.statusCode == 200) {
      return NumberTriviaModel.fromJson(json.decode(response.body));
    } else {
      throw ServerExceptions();
    }
  }

to check a method that has dio method inside it?

from http-mock-adapter.

theiskaa avatar theiskaa commented on May 27, 2024 1

Hi @tazik561
I tried fix your problem by initializing dio: ^3.0.9 and http_mock_adapter: ^0.1.6.
And I fixed it, It's simple you just need to change your expected value to:

expect(() async => await dio.post(path), throwsA(isA<DioError>()));

Just that, and I said that in this answer.

from http-mock-adapter.

LukaGiorgadze avatar LukaGiorgadze commented on May 27, 2024 1

@theiskaa i guess we resolved this in #100 PR, right?

from http-mock-adapter.

Alvarocda avatar Alvarocda commented on May 27, 2024 1

same problem here

from http-mock-adapter.

theiskaa avatar theiskaa commented on May 27, 2024

Hi @erayerdin first of all thanks for your response!

In your test code I can see you did mocking some request by this path:

/players/GET/{your data here}/{includeRecords: true, includeStats: true, userIds: foobar}/{}

and you get error by this path:

/players/GET/null/{includeRecords: true, includeStats: true, userIds: foobar}/{}

So your test code's path and real code's path are different.
However in your real code you didn't give data and that's why your data's place is null.
Just try giving same data, path and variables, if something goes wrong please tell us, write down in this issue or fill a new one.

from http-mock-adapter.

theiskaa avatar theiskaa commented on May 27, 2024

Hi @tazik561
I tried fix your problem by initializing dio: ^3.0.9 and http_mock_adapter: ^0.1.6.
And I fixed it, It's simple you just need to change your expected value to:

expect(() async => await dio.post(path), throwsA(isA<DioError>()));

Just that, and I said that in this answer.

I don't want to test dio directly . As I mention above I have a method called : getConcreteNumberTrivia.

  Future<NumberTriviaModel> getConcreteNumberTrivia(String url) async {
    final response =
        await dio.get(url, headers: {'Content-Type': 'application/json'});

    if (response.statusCode == 200) {
      return NumberTriviaModel.fromJson(json.decode(response.body));
    } else {
      throw ServerExceptions();
    }
  }

I am trying write test for this method getConcreteNumberTrivia. Inside this method there is a dio .Now I want when parser rich to dio, dio throw an error or exception .

In this answer we just test dio directly. But I want to test a method that has dio part like repository layer.

for example

setupMockHttpClientFailure404(){
      dioAdapterMockito.onPost(
        path,
        (request) => request.throws(404, dioError),
        headers: {'Content-Type': 'application/json; charset=utf-8'},
      );
}
    test(
      'should throw a ServerException when the responce code is 404 or other ',
      () async {
        setupMockHttpClientFailure404();
        final call = dataSource.getConcreteNumberTrivia;
        expect(call(url), throwsA(TypeMatcher<ServerExceptions>()));
      },
    );

I call final call = dataSource.getConcreteNumberTrivia; in test, In getConcreteNumberTrivia method when parser rich to final response = await dio.get(url, headers: {'Content-Type': 'application/json'}); , throw an exception.

@tazik561 Okay, as I understand it, you have a dio and that one isn't into your method right? So you wanna test your method, then you shouldn't test dio directly, yeah that is correct. But it's interesting where you do set dio class? you have to do same thing what are you doing when you are testing dio directly. Just set you dio's httpClientAdapter and go on!

from http-mock-adapter.

maurodibert avatar maurodibert commented on May 27, 2024

Hi guys! I'm trying to solve this and there is no way!
I have this class:

import 'dart:io';
import 'package:dio/dio.dart';

/// Dio requests types
enum Method {
  /// post
  post,

  /// get
  get,

  /// put
  put,

  /// delete
  delete,

  /// patch
  patch,
}

/// {@template http_service}
/// A service for managing requests
/// {@endtemplate}
class HttpService {
  /// {@macro http_service}
  HttpService({
    required Dio httpClient,
  }) : _httpClient = httpClient {
    init(httpClient: _httpClient);
  }

  late Dio _httpClient;

  /// service initialization and configuration
  Future<HttpService> init({
    required Dio httpClient,
  }) async {
    _httpClient = httpClient;
    return this;
  }

  /// help in handling request methods
  Future<Response> request({
    required String endpoint,
    required Method method,
    Map<String, dynamic>? params,
  }) async {
    Response response;

    try {
      if (method == Method.post) {
        response = await _httpClient.post<dynamic>(endpoint, data: params);
      } else if (method == Method.delete) {
        response = await _httpClient.delete<dynamic>(endpoint);
      } else if (method == Method.patch) {
        response = await _httpClient.patch<dynamic>(endpoint);
      } else {
        response =
            await _httpClient.get<dynamic>(endpoint, queryParameters: params);
      }

      if (response.statusCode == 200) {
        return response;
      } else if (response.statusCode == 401) {
        throw Exception('Unauthorized');
      } else if (response.statusCode == 500) {
        throw Exception('Server Error');
      } else {
        throw Exception("Something does wen't wrong");
      }
    } on SocketException catch (e) {
      throw Exception('Not Internet Connection');
    } on FormatException catch (e) {
      throw Exception('Bad response format');
    } on DioError catch (e) {
      throw Exception(e);
    } catch (e) {
      throw Exception("Something wen't wrong");
    }
  }
}

And trying to test errors and exceptions with this:

test('should return a Server Error Exception', () async { 
        dioAdapter.onPost(
          '/endpoint',
          (server) => server.throws(500, Constants.dioError),
          data: <String, dynamic>{},
          headers: Constants.edamamPostHeader,
        );

        expect(
          () async => await httpService.request(
            endpoint: '/endpoint',
            method: Method.post,
            params: <String, dynamic>{},
          ),
          isA<DioError>,
        );
      });

But could not resolve correctly the expectation:

Expected: <Closure: () => TypeMatcher<DioError> from Function 'isA': static.>
  Actual: <Closure: () => Future<Response<dynamic>>>

Any thoughts? Thanks in advance!

from http-mock-adapter.

maurodibert avatar maurodibert commented on May 27, 2024

I did this which I think is correct. What do you think?
image
image

from http-mock-adapter.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.