我正在嘗試使用 mockito 在 http.Client 呼叫中回傳虛假回應并能夠測驗服務。我已按照檔案進行操作。它告訴我應該使用annotate 來生成一個假類,但似乎flutter 的null safe 引起了問題。有誰知道怎么做?修復它謝謝
movies_provider_test.dart
import 'package:http/http.dart' as http;
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:watch_movie_app/src/data/data_source/remote/http_request.dart';
import 'package:watch_movie_app/src/data/models/models.dart';
import 'package:watch_movie_app/src/domain/services/movie_service.dart';
import 'package:watch_movie_app/src/environment_config.dart';
import 'mocks/popular_movies.dart';
import 'movies_provider_test.mocks.dart';
@GenerateMocks([http.Client])
void main() {
test('returns an movies if the http call completes sucessfully', () async {
final mockHttp = MockClient();
final container = ProviderContainer(
overrides: [
httpClientProvider.overrideWithValue(HttpRequest(httpClient: mockHttp)),
],
);
addTearDown(container.dispose);
final environmentConfig = container.read(environmentConfigProvider);
final movieService = container.read(movieServiceProvider);
String urlApi =
"${environmentConfig.domainApi}/${environmentConfig.apiVersion}/tv/popular?api_key=${environmentConfig.movieApiKey}&language=en-US&page=1";
Uri url = Uri.parse(urlApi);
when(mockHttp.get(url)).thenAnswer(
(_) async => http.Response(fakeMovies, 200),
);
expectLater(await movieService.getMovies(), isInstanceOf<List<Movie>>());
});
}
電影服務.dart
import 'package:http/http.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:watch_movie_app/src/data/data_source/remote/http_request.dart';
import 'package:watch_movie_app/src/domain/enums/enums.dart';
import 'package:watch_movie_app/src/data/models/models.dart';
import 'package:watch_movie_app/src/environment_config.dart';
import 'package:watch_movie_app/src/helpers/movie_api_exception.dart';
final movieServiceProvider = Provider<MovieService>((ref) {
final config = ref.read(environmentConfigProvider);
final httpRequest = ref.read(httpClientProvider);
return MovieService(config, httpRequest);
});
class MovieService {
final EnvironmentConfig _environmentConfig;
final HttpRequest _http;
MovieService(this._environmentConfig, this._http);
Future<List<Movie>> getMovies() async {
try {
String url =
"${_environmentConfig.domainApi}/${_environmentConfig.apiVersion}/tv/popular?api_key=${_environmentConfig.movieApiKey}&language=en-US&page=1";
final response =
await _http.request(typeHttp: EnumHttpType.get, urlApi: url);
if (response.statusCode != 200) {
throw const MovieApiException('Error al consulta las series populares');
}
List<Movie> movies = allMoviesFromJson(response.body);
return movies;
} on ClientException {
throw const MovieApiException('Error al consultar la información');
}
}
Future<List<Movie>> getMoviesRecommendations() async {
try {
String url =
"${_environmentConfig.domainApi}/${_environmentConfig.apiVersion}/tv/top_rated?api_key=${_environmentConfig.movieApiKey}&language=en-US&page=1";
final response =
await _http.request(typeHttp: EnumHttpType.get, urlApi: url);
if (response.statusCode != 200) {
throw const MovieApiException(
'Error al consulta las series recomendadas');
}
List<Movie> movies = allMoviesFromJson(response.body);
return movies;
} on ClientException {
throw const MovieApiException('Error al consultar los recomendados');
}
}
Future<MovieExtend> getDetailMovie(int id) async {
try {
String url =
"${_environmentConfig.domainApi}/${_environmentConfig.apiVersion}/tv/$id?api_key=${_environmentConfig.movieApiKey}&language=en-US&page=1";
final Response response =
await _http.request(typeHttp: EnumHttpType.get, urlApi: url);
if (response.statusCode != 200) {
throw const MovieApiException(
'Error al consulta el detalle de la serie');
}
MovieExtend movieExtend = movieExtendFromJson(response.body);
return movieExtend;
} on ClientException {
throw const MovieApiException(
'Error al consultar el detalle de la serie');
}
}
Future<List<Movie>> getAirtodayMovies() async {
try {
String url =
"${_environmentConfig.domainApi}/${_environmentConfig.apiVersion}/tv/airing_today?api_key=${_environmentConfig.movieApiKey}&language=en-US&page=1";
final Response response =
await _http.request(typeHttp: EnumHttpType.get, urlApi: url);
if (response.statusCode != 200) {
throw const MovieApiException(
'Error al consultar las series, intente nuevamente mas tarde');
}
List<Movie> movies = allMoviesFromJson(response.body);
return movies;
} on ClientException {
throw const MovieApiException('Error al consultar las series de hoy');
}
}
}
htt_request.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;
import 'package:watch_movie_app/src/domain/enums/enums.dart';
/// Clase que nos permite hacer peticiones Http
/// usando la libreria http.dar
class HttpRequest {
final http.Client _httpClient;
late String? token;
HttpRequest({http.Client? httpClient})
: _httpClient = httpClient ?? http.Client();
Future<http.Response> request(
{required EnumHttpType typeHttp, required String urlApi, data}) async {
Map<String, String> headers = {'Content-Type': 'application/json'};
Uri url = Uri.parse(urlApi);
switch (typeHttp) {
case EnumHttpType.post:
return _httpClient.post(url, body: data, headers: headers);
case EnumHttpType.get:
return _httpClient.get(url, headers: headers);
case EnumHttpType.patch:
return _httpClient.patch(url, headers: headers);
case EnumHttpType.put:
return _httpClient.put(url, headers: headers);
case EnumHttpType.delete:
return _httpClient.delete(url, headers: headers);
default:
return _httpClient.get(url);
}
}
}
final httpClientProvider = Provider<HttpRequest>((ref) => HttpRequest());
錯誤詳情
MissingStubError: 'get'
No stub was found which matches the arguments of this method call:
get(https://api.themoviedb.org/3/tv/popular?api_key=4dc138c853e44e4ea1d3dfd746fe451d&language=en-US&page=1, {headers: {Content-Type: application/json}}\)
Add a stub for this method using Mockito's 'when' API, or generate the MockClient mock with a MockSpec with 'returnNullOnMissingStub: true' (see https://pub.dev/documentation/mockito/latest/annotations/MockSpec-class.html\).
package:mockito/src/mock.dart 191:7 Mock._noSuchMethod
package:mockito/src/mock.dart 185:45 Mock.noSuchMethod
test\movies_provider_test.mocks.dart 45:14 MockClient.get
package:watch_movie_app/src/data/data_source/remote/http_request.dart 23:28 HttpRequest.request
package:watch_movie_app/src/domain/services/movie_service.dart 26:23 MovieService.getMovies
test\movies_provider_test.dart 36:36 main.<fn>
test\movies_provider_test.dart 17:68
鏈接檔案: 模擬單元測驗
uj5u.com熱心網友回復:
手動模擬http.Client
很棘手。存根必須完全匹配引數。在您的情況下,您為以下內容創建了一個存根:
when(mockHttp.get(url)).thenAnswer(...);
但錯誤表明實際呼叫的是什么:
No stub was found which matches the arguments of this method call:
get(<Long URL omitted>, {headers: {Content-Type: application/json}}\)
您的存根未注冊提供headers
引數的呼叫。
您確實應該避免嘗試創建手動模擬,http.Client
而是使用由. 它更容易使用。MockClient
package:http
uj5u.com熱心網友回復:
確實,正如我的同事@jamesdlin 評論的那樣,解決方案是使用 MockClient 類,下面我分享了正常作業的實作,以防有人遇到這個問題,非常感謝 jamesdlin
import 'package:http/http.dart' as http;
import 'package:http/testing.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:watch_movie_app/src/data/data_source/remote/http_request.dart';
import 'package:watch_movie_app/src/data/models/models.dart';
import 'package:watch_movie_app/src/domain/services/movie_service.dart';
import 'mocks/popular_movies.dart';
void main() {
test('returns an instance of movies if the http call completed sucessfully',
() async {
final mockHttp = MockClient((_) async => http.Response(fakeMovies, 200));
final container = ProviderContainer(
overrides: [
httpClientProvider.overrideWithValue(HttpRequest(httpClient: mockHttp)),
],
);
addTearDown(container.dispose);
final movieService = container.read(movieServiceProvider);
expectLater(await movieService.getMovies(), isInstanceOf<List<Movie>>());
});
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/445223.html
上一篇:為什么在CupertinoApp中更改導航欄的背景顏色會改變高度?
下一篇:用url中的字串替換域擴展名