Skip to content

Commit 1c38ea1

Browse files
authored
Merge pull request #10 from VB10/feature/tdd
Unit Test
2 parents de4f818 + 23c6b76 commit 1c38ea1

File tree

11 files changed

+305
-6
lines changed

11 files changed

+305
-6
lines changed

lib/core/init/network/ICoreDio.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ abstract class ICoreDio {
99
{@required HttpTypes type,
1010
@required T parseModel,
1111
dynamic data,
12-
Map<String, dynamic> queryParameters,
12+
Map<String, Object> queryParameters,
13+
void Function(int, int) onReceiveProgress});
14+
}
15+
16+
abstract class ICoreDioFull extends ICoreDio {
17+
Future<IResponseModel<R>> fetchNoNetwork<R, T extends BaseModel>(String path,
18+
{@required HttpTypes type,
19+
@required T parseModel,
20+
dynamic data,
21+
Map<String, Object> queryParameters,
1322
void Function(int, int) onReceiveProgress});
1423
}

lib/core/init/network/core_dio.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class CoreDio with DioMixin implements Dio, ICoreDio {
3232
switch (response.statusCode) {
3333
case HttpStatus.ok:
3434
case HttpStatus.accepted:
35-
final model = _responseParser<R>(parseModel, _responseParser);
35+
final model = _responseParser<R, T>(parseModel, response.data);
3636
return ResponseModel<R>(data: model);
3737
default:
3838
return ResponseModel(error: BaseError("message"));

lib/core/init/network/network_core/core_operations.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
part of "../core_dio.dart";
22

33
extension _CoreDioOperations on CoreDio {
4-
R _responseParser<R>(BaseModel model, dynamic data) {
4+
R _responseParser<R, T>(BaseModel model, dynamic data) {
55
if (data is List) {
6-
return data.map((e) => model.fromJson(e)).toList() as R;
6+
return data.map((e) => model.fromJson(e)).toList().cast<T>() as R;
77
} else if (data is Map) {
88
return model.fromJson(data) as R;
99
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:fluttermvvmtemplate/core/extension/string_extension.dart';
3+
4+
main() {
5+
setUp(() {});
6+
test("Email Regexp", () {
7+
String email = "joedoe@gmail.com";
8+
expect(email.isValidEmail, null);
9+
});
10+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import 'dart:convert';
2+
import 'dart:io';
3+
4+
import 'package:dio/adapter.dart';
5+
import 'package:dio/dio.dart';
6+
import 'package:easy_localization/easy_localization.dart';
7+
import 'package:flutter_test/flutter_test.dart';
8+
import 'package:fluttermvvmtemplate/core/base/model/base_error.dart';
9+
import 'package:fluttermvvmtemplate/core/constants/enums/http_request_enum.dart';
10+
import 'package:fluttermvvmtemplate/core/base/model/base_model.dart';
11+
import 'package:fluttermvvmtemplate/core/extension/network_exntension.dart';
12+
import 'package:fluttermvvmtemplate/core/init/network/ICoreDio.dart';
13+
import 'package:fluttermvvmtemplate/core/init/network/IResponseModel.dart';
14+
15+
class CoreDioMock with DioMixin implements ICoreDioFull, Dio {
16+
final BaseOptions options;
17+
18+
CoreDioMock(this.options) {
19+
this.options = options;
20+
this.interceptors.add(InterceptorsWrapper());
21+
this.httpClientAdapter = DefaultHttpClientAdapter();
22+
}
23+
@override
24+
Future<IResponseModel<R>> fetch<R, T extends BaseModel>(String path,
25+
{HttpTypes type,
26+
T parseModel,
27+
data,
28+
Map<String, Object> queryParameters,
29+
void Function(int p1, int p2) onReceiveProgress}) async {
30+
final response = await request(path, data: data, options: Options(method: type.rawValue));
31+
32+
switch (response.statusCode) {
33+
case HttpStatus.ok:
34+
case HttpStatus.accepted:
35+
final model = _responseParser<R, T>(parseModel, response.data);
36+
return ResponseModel<R>(data: model);
37+
default:
38+
return ResponseModel(error: BaseError("message"));
39+
}
40+
}
41+
42+
Future<IResponseModel<R>> fetchNoNetwork<R, T extends BaseModel>(String path,
43+
{HttpTypes type,
44+
T parseModel,
45+
data,
46+
Map<String, Object> queryParameters,
47+
void Function(int p1, int p2) onReceiveProgress}) async {
48+
String dumyJson = """[
49+
{
50+
"userId": 1,
51+
"id": 1,
52+
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
53+
"body": "quia et suscipit suscipit recusandae consequuntur expedita et cumnreprehenderit molestiae ut ut quas totamnostrum rerum est autem sunt rem eveniet architecto"
54+
},
55+
{
56+
"userId": 1,
57+
"id": 2,
58+
"title": "qui est esse",
59+
"body": "est rerum tempore vitaensequi sint nihil reprehenderit dolor beatae ea dolores nequenfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendisnqui aperiam non debitis possimus qui neque nisi nulla"
60+
}]""";
61+
final response = jsonDecode(dumyJson);
62+
final model = _responseParser<R, T>(parseModel, response);
63+
return ResponseModel<R>(data: model);
64+
}
65+
66+
R _responseParser<R, T>(BaseModel model, dynamic data) {
67+
if (data is List) {
68+
return data.map((e) => model.fromJson(e)).toList().cast<T>() as R;
69+
} else if (data is Map) {
70+
return model.fromJson(data) as R;
71+
}
72+
return data as R;
73+
}
74+
}
75+
76+
class Dio {}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import 'package:dio/dio.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:fluttermvvmtemplate/core/constants/enums/http_request_enum.dart';
4+
import 'package:fluttermvvmtemplate/core/init/network/ICoreDio.dart';
5+
import 'core_dio_mock.dart';
6+
import 'dio_mock_model.dart';
7+
8+
main() {
9+
ICoreDioFull service;
10+
setUp(() {
11+
service = CoreDioMock(BaseOptions(baseUrl: "https://jsonplaceholder.typicode.com"));
12+
});
13+
test("CoreDio List", () async {
14+
final data =
15+
await service.fetch<List<PostModel>, PostModel>("/posts", type: HttpTypes.GET, parseModel: PostModel());
16+
17+
expect(data.data, isList);
18+
});
19+
20+
test("CoreDio List No Network", () async {
21+
final data = await service.fetchNoNetwork<List<PostModel>, PostModel>("/posts",
22+
type: HttpTypes.GET, parseModel: PostModel());
23+
24+
expect(data.data, isList);
25+
});
26+
27+
test("CoreDio Object", () async {
28+
final data =
29+
await service.fetch<List<PostModel>, PostModel>("/posts", type: HttpTypes.GET, parseModel: PostModel());
30+
31+
expect(data.data, isList);
32+
});
33+
34+
test("CoreDio Primitive", () async {
35+
final data =
36+
await service.fetch<List<PostModel>, PostModel>("/posts", type: HttpTypes.GET, parseModel: PostModel());
37+
38+
expect(data.data, isList);
39+
});
40+
41+
test("CoreDio Error", () async {
42+
final data = await service.fetchNoNetwork<List<PostModel>, PostModel>("/posts",
43+
type: HttpTypes.GET, parseModel: PostModel());
44+
45+
expect(data.data, isList);
46+
});
47+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import 'package:fluttermvvmtemplate/core/base/model/base_model.dart';
2+
3+
class PostModel extends BaseModel<PostModel> {
4+
int userId;
5+
int id;
6+
String title;
7+
String body;
8+
9+
PostModel({this.userId, this.id, this.title, this.body});
10+
11+
PostModel.fromJson(Map<String, dynamic> json) {
12+
userId = json['userId'];
13+
id = json['id'];
14+
title = json['title'];
15+
body = json['body'];
16+
}
17+
18+
Map<String, dynamic> toJson() {
19+
final Map<String, dynamic> data = new Map<String, dynamic>();
20+
data['userId'] = this.userId;
21+
data['id'] = this.id;
22+
data['title'] = this.title;
23+
data['body'] = this.body;
24+
return data;
25+
}
26+
27+
@override
28+
PostModel fromJson(Map<String, Object> json) {
29+
return PostModel.fromJson(json);
30+
}
31+
}

test/feature/login/login_test.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import 'package:flutter_test/flutter_test.dart';
22
import 'package:fluttermvvmtemplate/core/base/model/base_error.dart';
3-
import 'package:fluttermvvmtemplate/core/base/model/base_model.dart';
4-
import 'package:fluttermvvmtemplate/view/authenticate/test/model/test_model.dart';
53

64
main() {
75
setUp(() {
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import 'package:dio/dio.dart';
2+
import 'package:fluttermvvmtemplate/core/constants/enums/http_request_enum.dart';
3+
import 'package:fluttermvvmtemplate/core/init/network/core_dio.dart';
4+
import 'package:fluttermvvmtemplate/view/authenticate/onboard/model/on_board_model.dart';
5+
import 'package:fluttermvvmtemplate/core/init/network/ICoreDio.dart';
6+
import 'package:flutter/src/widgets/framework.dart';
7+
import 'package:fluttermvvmtemplate/view/authenticate/onboard/view-model/on_board_view_model.dart';
8+
9+
import '../../core/network/dio_mock_model.dart';
10+
11+
class OnBoardMockViewModel implements OnBoardViewModel {
12+
@override
13+
BuildContext context;
14+
15+
@override
16+
ICoreDio coreDio;
17+
18+
IStringHelper stringHelper;
19+
20+
@override
21+
int currentPageIndex;
22+
23+
bool isLoading = false;
24+
25+
@override
26+
List<OnBoardModel> onBoarModel;
27+
28+
@override
29+
void init() {
30+
coreDio = CoreDio(BaseOptions(baseUrl: "https://jsonplaceholder.typicode.com"));
31+
stringHelper = MockStringHelper();
32+
}
33+
34+
@override
35+
void onPageChanged(int value) {
36+
currentPageIndex = value;
37+
}
38+
39+
Future<void> onBoardGetModels() async {
40+
final response =
41+
await coreDio.fetch<List<PostModel>, PostModel>("/posts", type: HttpTypes.GET, parseModel: PostModel());
42+
43+
if (response.data is List) {
44+
onBoarModel = response.data.map((e) => OnBoardModel(stringHelper.toUpper(e.title))).toList().cast<OnBoardModel>();
45+
}
46+
}
47+
48+
Future<void> getServiceRequest() async {
49+
isLoading = true;
50+
await onBoardGetModels();
51+
isLoading = false;
52+
}
53+
54+
@override
55+
void setContext(BuildContext context) {}
56+
}
57+
58+
abstract class IStringHelper {
59+
String toUpper(String data);
60+
}
61+
62+
class MockStringHelper extends IStringHelper {
63+
@override
64+
String toUpper(String data) {
65+
return data.toUpperCase();
66+
}
67+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:shared_preferences/shared_preferences.dart';
3+
4+
import 'onboard_mock_view_model.dart';
5+
6+
main() {
7+
OnBoardMockViewModel mockViewModel;
8+
IStringHelper stringHelper;
9+
setUp(() {
10+
SharedPreferences.setMockInitialValues({"token": "asdasd"}); //set values here
11+
mockViewModel = OnBoardMockViewModel();
12+
stringHelper = MockStringHelper();
13+
mockViewModel.init();
14+
});
15+
test("String Helper Upper Case", () {
16+
String text = " Helelo";
17+
text = stringHelper.toUpper(text);
18+
expect(text.contains(RegExp("[A-Z\s]+")), true);
19+
});
20+
21+
test("OnBoard Get Models", () async {
22+
await mockViewModel.onBoardGetModels();
23+
expect(mockViewModel.onBoarModel, isNotEmpty);
24+
});
25+
26+
test("OnBoard Get Service Request", () async {
27+
expect(mockViewModel.isLoading, false);
28+
mockViewModel.getServiceRequest();
29+
expect(mockViewModel.isLoading, true);
30+
});
31+
32+
test("OnBoard On Page Changed", () {
33+
mockViewModel.onPageChanged(5);
34+
expect(5, mockViewModel.currentPageIndex);
35+
});
36+
37+
group("Test All", () {
38+
int index = 0;
39+
test("OnBoard Get Models", () async {
40+
await mockViewModel.onBoardGetModels();
41+
index = mockViewModel.onBoarModel.length;
42+
expect(mockViewModel.onBoarModel, isNotEmpty);
43+
});
44+
45+
test("OnBoard On Page Changed", () {
46+
mockViewModel.onPageChanged(index);
47+
expect(index, mockViewModel.currentPageIndex);
48+
});
49+
});
50+
}

0 commit comments

Comments
 (0)