Как издеваться над VideoPlayerController.network() во Flutter
Я пишу простой тест для своего виджета видеоплеера, который использует плагин video_player. Я не могу имитировать сетевой запрос видеоконтроллера на получение видео по сети. Код моего виджета выглядит так:
late VideoPlayerController _videoController;
@override
void initState() {
_videoController = VideoPlayerController.network(widget.videoUrl);
// rest of the code
}
и тестовый код:
VideoPlayerController _videoController =
VideoPlayerController.network(videoUrl);
when(VideoPlayerController.network(videoUrl))
.thenAnswer((_) => _videoController);
Это не работает, потому что он не может правильно заглушить метод сетевого запроса. Есть идеи для правильного издевательства? У меня есть несколько других тестов в моем коде, где я издевался над своим клиентским классом api, который выполняет сетевые запросы, но этот немного отличается. Я использую mockito для издевательств.
Пожалуйста помоги!
1 ответ
Решение. Вот как вы можете имитировать пакет video_player.
// On unit test, you can use following
VideoPlayerPlatform.instance = FakeVideoPlayerPlatform();
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
// For unit test
// ignore: depend_on_referenced_packages
import 'package:video_player_platform_interface/video_player_platform_interface.dart';
// Created from video_player package and video_player_test.dart file.
class FakeVideoPlayerPlatform extends VideoPlayerPlatform {
final Completer<bool> initialized = Completer<bool>();
final List<String> calls = <String>[];
final List<DataSource> dataSources = <DataSource>[];
final Map<int, StreamController<VideoEvent>> streams =
<int, StreamController<VideoEvent>>{};
final bool forceInitError;
int nextTextureId = 0;
final Map<int, Duration> _positions = <int, Duration>{};
FakeVideoPlayerPlatform({
this.forceInitError = false,
});
@override
Future<int?> create(DataSource dataSource) async {
calls.add('create');
final StreamController<VideoEvent> stream = StreamController<VideoEvent>();
streams[nextTextureId] = stream;
if (forceInitError) {
stream.addError(
PlatformException(
code: 'VideoError',
message: 'Video player had error XYZ',
),
);
} else {
stream.add(
VideoEvent(
eventType: VideoEventType.initialized,
size: const Size(100, 100),
duration: const Duration(seconds: 1),
),
);
}
dataSources.add(dataSource);
return nextTextureId++;
}
@override
Future<void> dispose(int textureId) async {
calls.add('dispose');
}
@override
Future<void> init() async {
calls.add('init');
initialized.complete(true);
}
@override
Stream<VideoEvent> videoEventsFor(int textureId) {
return streams[textureId]!.stream;
}
@override
Future<void> pause(int textureId) async {
calls.add('pause');
}
@override
Future<void> play(int textureId) async {
calls.add('play');
}
@override
Future<Duration> getPosition(int textureId) async {
calls.add('position');
return _positions[textureId] ?? Duration.zero;
}
@override
Future<void> seekTo(int textureId, Duration position) async {
calls.add('seekTo');
_positions[textureId] = position;
}
@override
Future<void> setLooping(int textureId, bool looping) async {
calls.add('setLooping');
}
@override
Future<void> setVolume(int textureId, double volume) async {
calls.add('setVolume');
}
@override
Future<void> setPlaybackSpeed(int textureId, double speed) async {
calls.add('setPlaybackSpeed');
}
@override
Future<void> setMixWithOthers(bool mixWithOthers) async {
calls.add('setMixWithOthers');
}
@override
Widget buildView(int textureId) {
return Texture(textureId: textureId);
}
}