Flutter网络媒体模拟插件network_media_mock的使用

Flutter网络媒体模拟插件network_media_mock的使用

简介

Network Media Mock 是一个强大的 Dart 包,用于在 Flutter 应用中模拟 HTTP 请求以获取媒体文件。它通过拦截 HTTP 请求并提供本地资源文件来模拟网络媒体响应,非常适合用于 测试原型设计演示 应用程序,而无需依赖实时服务器。

支持的小部件

该工具旨在与以下小部件无缝协作:

  • Image.network
  • CachedNetworkImage
  • SvgPicture.network

特性

  • 模拟媒体响应:直接从本地资源提供媒体文件(例如图像、PDF等),而不是从互联网上获取。
  • 自定义映射:轻松将URL或MIME类型映射到特定资源。
  • 正则表达式URL匹配:使用正则表达式模式定义和匹配URL进行模拟。
  • 类型识别:根据文件扩展名或URL模式自动检测MIME类型。
  • 灵活配置:自定义选项如响应延迟、日志记录和默认映射。

开始使用

安装

要使用 Network Media Mock,请按照以下步骤操作:

  1. pubspec.yaml 文件中添加包:
    dependencies:
      network_media_mock: <latest-version>
    
  2. 运行以下命令安装包:
    flutter pub get
    

使用方法

使用默认选项

最简单的使用方式是通过启用带有默认选项的Network Media Mock。这会自动将常见媒体类型映射到包的预定义资源。

import 'package:network_media_mock/network_media_mock.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  setUpAll(() {
    TestWidgetsFlutterBinding.ensureInitialized();

    // Initialize the package before any of test cases
    HttpOverrides.global = MockHttpOverrides(); // Use default options
  });

  testWidgets(
    'Test Image.network with file extension',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        Image.network(
          'https://anydomain.com/files/18813d1a.jpg',
        ),
      );

      // Your test logic goes here
    },
  );
}

高级使用与自定义选项

对于更多的控制,您可以提供诸如URL到类型映射、MIME类型到资源映射、日志记录和响应延迟等自定义选项。

import 'package:network_media_mock/network_media_mock.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  setUpAll(() {
    TestWidgetsFlutterBinding.ensureInitialized();

    // Initialize the package before any of test cases
    HttpOverrides.global = MockHttpOverrides(
      options: NetworkMediaMockOptions(
        isLogEnabled: true, // Enable logging
        responseDelay: const Duration(seconds: 2), // Add a delay to simulate network latency
        urlToTypeMappers: [
          UrlToTypeMapping(
            RegExp(r'https://example.com/api/files/.*'),
            MockMimeType.imageSvgXml,
          ),
          UrlToTypeMapping(
            RegExp(r'https://via.placeholder.com/600/.*'),
            MockMimeType.imagePng,
          ),
        ],
        typeToAssetMappers: [
          MimeTypeToAssetMapping(MockMimeType.imageJpeg, "assets/custom_image.jpg"),
          MimeTypeToAssetMapping(MockMimeType.applicationPdf, "assets/custom_doc.pdf"),
        ],
      ),
    );
  });

  testWidgets(
    'Test Image.network',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        Image.network('https://anydomain.com/files/18813d1a.jpg'),
      );

      // Your test logic goes here
    },
  );

  testWidgets(
    'Test SvgPicture.network',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        SvgPicture.network('https://example.com/api/files/18813d1a'),
      );

      // Your test logic goes here
    },
  );

  testWidgets(
    'Test CachedNetworkImage',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        CachedNetworkImage(
          imageUrl: 'https://via.placeholder.com/600/771796',
        ),
      );

      // Your test logic goes here
    },
  );
}

声明自定义资源

如果您使用自定义资源,请在应用程序的 pubspec.yaml 中声明它们:

flutter:
  assets:
    - assets/custom_image.jpg
    - assets/custom_doc.pdf

配置

NetworkMediaMockOptions

NetworkMediaMockOptions 类是主要的配置工具,用于自定义模拟系统的行为。以下是其关键属性:

  • isLogEnabled:启用日志记录以进行调试。当设置为 true 时,会打印指示是否对文件进行了模拟的日志。
  • responseDelay:模拟加载媒体文件的网络延迟。指定等待返回模拟文件之前的时间。
  • urlToTypeMappers:将特定URL映射到文件类型。这在无法从URL本身确定文件格式时特别有用。
  • typeToAssetMappers:将文件类型(例如 image/png, video/mp4)映射到自定义模拟文件。如果为一种类型提供了多个文件,则每次请求都会随机选择一个。此配置覆盖包的默认小型模拟文件。

示例代码

小部件测试

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:network_media_mock/network_media_mock.dart';

void main() {
  setUpAll(() {
    TestWidgetsFlutterBinding.ensureInitialized();
    HttpOverrides.global = MockHttpOverrides(
      options: NetworkMediaMockOptions(
        isLogEnabled: true,
        responseDelay: const Duration(seconds: 2),
        urlToTypeMappers: [
          UrlToTypeMapping(
            RegExp(r'https://example.com/api/files/.*'),
            MockMimeType.imageSvgXml,
          ),
        ],
      ),
    );
  });

  testWidgets(
    'Test Image.network',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        Image.network(
          'https://anydomain.com/files/18813d1a.jpg',
          loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
            if (loadingProgress?.cumulativeBytesLoaded == loadingProgress?.expectedTotalBytes) {
              return child;
            }
            return const CircularProgressIndicator();
          },
          errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) {
            return const Text('Image.network error');
          },
        ),
      );

      await tester.pump(const Duration(milliseconds: 200));
      expect(find.byType(CircularProgressIndicator), findsOneWidget);
      await tester.pumpAndSettle();
      expect(find.text('Image.network error'), findsNothing);
    },
  );

  testWidgets(
    'Test SvgPicture.network',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        SvgPicture.network(
          'https://example.com/api/files/18813d1a',
          placeholderBuilder: (context) => const CircularProgressIndicator(),
        ),
      );

      expect(find.byType(CircularProgressIndicator), findsOneWidget);
      await tester.pumpAndSettle();
      expect(find.byType(CircularProgressIndicator), findsNothing);
    },
  );
}

集成测试

使用以下命令运行集成测试:

flutter test integration_test/app_integration_test.dart
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:network_media_mock/network_media_mock.dart';

void main() {
  setUpAll(() {
    IntegrationTestWidgetsFlutterBinding.ensureInitialized();
    HttpOverrides.global = MockHttpOverrides(
      options: NetworkMediaMockOptions(
        isLogEnabled: true,
        responseDelay: const Duration(milliseconds: 500),
        urlToTypeMappers: [
          UrlToTypeMapping(
            RegExp(r'https://via.placeholder.com/600/.*'),
            MockMimeType.imagePng,
          ),
        ],
      ),
    );
  });

  testWidgets(
    'Test CachedNetworkImage',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        CachedNetworkImage(
          imageUrl: 'https://via.placeholder.com/600/771796',
          placeholder: (context, url) {
            return const CircularProgressIndicator();
          },
          errorWidget: (context, url, error) {
            return const Text('CachedNetworkImage Failed');
          },
        ),
      );

      await tester.pump(const Duration(milliseconds: 200));
      expect(find.byType(CircularProgressIndicator), findsOneWidget);
      await tester.pumpAndSettle();
      expect(find.text('CachedNetworkImage Failed'), findsNothing);
    },
  );
}

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

1 回复

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


在Flutter中,network_media_mock插件通常用于模拟网络媒体播放的场景,特别是在进行单元测试或集成测试时,无需依赖实际的网络资源。以下是如何在Flutter项目中集成和使用network_media_mock插件的一个基本示例。

首先,确保你已经在pubspec.yaml文件中添加了network_media_mock依赖项:

dependencies:
  flutter:
    sdk: flutter
  network_media_mock: ^最新版本号  # 请替换为实际的最新版本号

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

接下来,在你的Flutter项目中,你可能会有一个使用网络媒体播放的组件或服务。为了演示如何使用network_media_mock,我们假设你有一个简单的视频播放器组件。

示例代码

1. 创建一个视频播放器组件

import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:network_media_mock/network_media_mock.dart'; // 引入mock包

class VideoPlayerScreen extends StatefulWidget {
  @override
  _VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}

class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  VideoPlayerController? _controller;

  @override
  void initState() {
    super.initState();
    // 使用mock URL初始化控制器(这里假设有一个mock的URL)
    _controller = VideoPlayerController.network(
      NetworkMediaMock.mockVideoUrl, // 使用mock的URL
    )..initialize().then((_) {
      setState(() {});
    });
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Video Player Demo'),
      ),
      body: Center(
        child: _controller?.value.isInitialized
            ? AspectRatio(
                aspectRatio: _controller!.value.aspectRatio,
                child: VideoPlayer(_controller!),
              )
            : Container(
                child: CircularProgressIndicator(),
              ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            _controller?.value.isPlaying
                ? _controller!.pause()
                : _controller!.play();
          });
        },
        child: Icon(
          _controller?.value.isPlaying ?? false
              ? Icons.pause
              : Icons.play_arrow,
        ),
      ),
    );
  }
}

2. 配置测试环境使用Mock

在测试环境中,你可能需要配置network_media_mock来返回一个模拟的视频流。这通常在测试文件中完成。

import 'package:flutter_test/flutter_test.dart';
import 'package:network_media_mock/network_media_mock.dart';
import 'package:your_app/video_player_screen.dart'; // 替换为你的视频播放器组件路径

void main() {
  testWidgets('VideoPlayerScreen plays and pauses video', (WidgetTester tester) async {
    // 设置mock视频URL返回的数据
    await NetworkMediaMock.setupMockNetworkImages(() {
      return 'path/to/your/mock/video.mp4'; // 这里返回一个本地或模拟的视频文件路径
    });

    await tester.pumpWidget(MaterialApp(
      home: VideoPlayerScreen(),
    ));

    // 等待视频初始化完成
    await tester.pumpAndSettle();

    // 查找播放按钮并触发点击事件
    final playButtonFinder = find.byIcon(Icons.play_arrow);
    expect(playButtonFinder, findsOneWidget);
    await tester.tap(playButtonFinder);
    await tester.pumpAndSettle();

    // 验证视频是否正在播放
    final videoPlayerFinder = find.byType(VideoPlayer);
    expect(videoPlayerFinder, findsOneWidget);
    final VideoPlayer videoPlayer = tester.widget(videoPlayerFinder)!;
    expect(videoPlayer.controller!.value.isPlaying, isTrue);

    // 再次点击播放按钮以暂停视频
    await tester.tap(playButtonFinder);
    await tester.pumpAndSettle();
    expect(videoPlayer.controller!.value.isPlaying, isFalse);
  });
}

注意:上面的测试代码示例假设network_media_mock能够直接模拟视频流,但在实际应用中,模拟视频流可能涉及更复杂的设置,比如使用HTTP服务器模拟返回视频内容。此外,由于network_media_mock的具体实现可能有所不同,你需要根据该插件的文档和API来调整代码。

在实际项目中,务必参考network_media_mock的官方文档和示例代码,以确保正确集成和使用。

回到顶部