Flutter网络请求模拟插件http_mock_adapter的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter网络请求模拟插件http_mock_adapter的使用

描述

http_mock_adapter 是一个简单易用的用于 Dio 的模拟包,旨在用于测试中。它提供了多种类型和方法以声明式的方式模拟请求-响应通信。

使用方法

下面是一个非常基础的使用场景:

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

void main() async {
  // Basic setup
  final dio = Dio(BaseOptions());
  final dioAdapter = DioAdapter(dio: dio);

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

  dioAdapter.onGet(
    path,
    (server) => server.reply(
      200,
      {'message': 'Success!'},
      // Reply would wait for one-sec before returning data.
      delay: const Duration(seconds: 1),
    ),
  );

  final response = await dio.get(path);

  print(response.data); // {message: Success!}
}

实际案例

该包的主要用途是在尝试模拟与服务器的请求-响应通信行为时,在测试中使用。示例展示了如何在实际项目中利用此包。

安装

快速安装

你可以通过命令行快速安装该包:

使用 dart:

$ dart pub add --dev http_mock_adapter
...

使用 flutter:

$ flutter pub add --dev http_mock_adapter
...

手动安装

依赖于它

在你的项目的 pubspec.yaml 文件中添加以下内容:

dev_dependencies:
  http_mock_adapter: ^0.6.1

安装它

然后你可以通过命令行安装该包:

使用 dart:

$ dart pub get
...

使用 flutter:

$ flutter pub get
...

或者,你的编辑器可能支持 dart pub getflutter pub get。请查阅你的编辑器文档以了解更多。

导入它

现在在你的 Dart 代码中,你可以使用:

import 'package:http_mock_adapter/http_mock_adapter.dart';

更多信息

  • 变更日志: 查看CHANGELOG.md了解所有显著的变化。
  • 作者: 参见AUTHORS文件获取项目作者的信息。
  • 许可证: http-mock-adapter 采用宽松的 MIT 许可证(LICENSE)。
  • 贡献: 对于有关贡献的信息,请参阅CONTRIBUTING.md文件。

示例代码

以下是更详细的示例代码,演示了如何在测试中使用 http_mock_adapter 模拟用户注册、登录和获取账户信息的过程。

import 'package:dio/dio.dart';
import 'package:http_mock_adapter/http_mock_adapter.dart';
import 'package:test/test.dart';

void main() async {
  late Dio dio;
  late DioAdapter dioAdapter;

  Response<dynamic> response;

  group('Accounts', () {
    const baseUrl = 'https://example.com';

    const userCredentials = <String, dynamic>{
      'email': 'test@example.com',
      'password': 'password',
    };

    setUp(() {
      dio = Dio(BaseOptions(baseUrl: baseUrl));
      dioAdapter = DioAdapter(
        dio: dio,
        matcher: const FullHttpRequestMatcher(),
      );
    });

    test('signs up user', () async {
      const route = '/signup';

      dioAdapter.onPost(
        route,
        (server) => server.reply(
          201,
          null,
          delay: const Duration(seconds: 1),
        ),
        data: userCredentials,
      );

      response = await dio.post(route, data: userCredentials);

      expect(response.statusCode, 201);
    });

    test('signs in user and fetches account information', () async {
      const signInRoute = '/signin';
      const accountRoute = '/account';

      const accessToken = <String, dynamic>{
        'token': 'ACCESS_TOKEN',
      };

      final headers = <String, dynamic>{
        'Authentication': 'Bearer ${accessToken['token']}',
      };

      const userInformation = <String, dynamic>{
        'id': 1,
        'email': 'test@example.com',
        'password': 'password',
        'email_verified': false,
      };

      dioAdapter
        ..onPost(
          signInRoute,
          (server) => server.throws(
            401,
            DioException(
              requestOptions: RequestOptions(
                path: signInRoute,
              ),
            ),
          ),
        )
        ..onPost(
          signInRoute,
          (server) => server.reply(200, accessToken),
          data: userCredentials,
        )
        ..onGet(
          accountRoute,
          (server) => server.reply(200, userInformation),
          headers: headers,
        );

      // Throws without user credentials.
      expect(
        () async => await dio.post(signInRoute),
        throwsA(isA<DioException>()),
      );

      // Returns an access token if user credentials are provided.
      response = await dio.post(signInRoute, data: userCredentials);

      expect(response.data, accessToken);

      // Returns user information if an access token is provided in headers.
      response = await dio.get(
        accountRoute,
        options: Options(headers: headers),
      );

      expect(response.data, userInformation);
    });
  });
}

以上是关于 http_mock_adapter 插件的详细介绍及使用示例。希望这些信息能帮助你在Flutter项目中更好地进行网络请求模拟测试。


更多关于Flutter网络请求模拟插件http_mock_adapter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter网络请求模拟插件http_mock_adapter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用http_mock_adapter插件来进行网络请求模拟的代码示例。这个插件允许你在开发过程中拦截和模拟HTTP请求,而无需依赖实际的后端服务。

1. 添加依赖

首先,你需要在你的pubspec.yaml文件中添加http_mock_adapter依赖:

dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.3  # 确保你也添加了http包,因为http_mock_adapter依赖于它
  http_mock_adapter: ^0.4.0  # 请检查最新版本号

然后运行flutter pub get来安装依赖。

2. 配置项目

在你的Flutter项目中,你可以创建一个服务来进行网络请求,并使用http_mock_adapter来模拟这些请求。以下是一个简单的示例:

创建一个数据模型

假设我们有一个简单的用户数据模型:

class User {
  final int id;
  final String name;

  User({required this.id, required this.name});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'] as int,
      name: json['name'] as String,
    );
  }
}

创建一个服务类

接下来,我们创建一个服务类来进行网络请求:

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:http_mock_adapter/http_mock_adapter.dart';

class UserService {
  final http.Client client;
  late HttpMockAdapter mockAdapter;

  UserService({required this.client}) {
    mockAdapter = HttpMockAdapter(client);
  }

  Future<User?> fetchUser(int id) async {
    final response = await client.get(Uri.parse('https://api.example.com/users/$id'));

    if (response.statusCode == 200) {
      final Map<String, dynamic> body = jsonDecode(response.body);
      return User.fromJson(body);
    } else {
      throw Exception('Failed to load user');
    }
  }
}

使用服务并模拟请求

在你的小部件或ViewModel中,你可以这样使用UserService并模拟HTTP请求:

import 'package:flutter/material.dart';
import 'user_service.dart';
import 'user_model.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('HTTP Mock Adapter Example'),
        ),
        body: UserFetchExample(),
      ),
    );
  }
}

class UserFetchExample extends StatefulWidget {
  @override
  _UserFetchExampleState createState() => _UserFetchExampleState();
}

class _UserFetchExampleState extends State<UserFetchExample> {
  late UserService userService;
  User? user;
  String status = '';

  @override
  void initState() {
    super.initState();
    final http.Client client = http.Client();
    userService = UserService(client: client);

    // 模拟一个HTTP GET请求
    userService.mockAdapter.onGet(
      Uri.parse('https://api.example.com/users/1'),
      (req, res) => res.replyJson(200, {'id': 1, 'name': 'John Doe'}),
    );

    // 发起请求
    fetchUser();
  }

  @override
  void dispose() {
    userService.mockAdapter.close();
    super.dispose();
  }

  Future<void> fetchUser() async {
    try {
      user = await userService.fetchUser(1);
      setState(() {
        status = 'User fetched successfully!';
      });
    } catch (e) {
      setState(() {
        status = 'Failed to fetch user: $e';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(status),
          if (user != null)
            Text('User: ${user!.name}'),
        ],
      ),
    );
  }
}

在这个示例中,我们创建了一个UserService类来处理网络请求,并在UserFetchExample小部件中模拟了一个HTTP GET请求。我们使用了mockAdapter.onGet方法来拦截特定的URL并返回一个模拟的JSON响应。

这样,你就可以在开发过程中使用模拟数据,而不必依赖后端服务。这对于测试UI逻辑和确保应用在各种数据条件下都能正确工作非常有用。

回到顶部