Firebase Flutter unit testing Firebase.initializeApp() - flutter

It's my first time testing an app I tried to test firebase auth and had this error
I also search in the doc but everything is outdated or doesn't implement firebase
This is my code
import 'package:ecommerce/main.dart';
import 'package:ecommerce/services/auth.dart';
import 'package:fake_cloud_firestore/fake_cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:rxdart/subjects.dart';
class MockFirebaseAuth extends Mock implements FirebaseAuth {}
class MockFirebaseUser extends Mock implements User {}
class MockUserCredential extends Mock implements Future<UserCredential> {}
void main() {
MockFirebaseAuth _auth = MockFirebaseAuth();
MockUserCredential mockUserCredential = MockUserCredential();
AuthService authManager = AuthService();
final instance = FakeFirebaseFirestore();
group("User Auth Test", () {
test('Returns no user if not signed in', () async {
final auth = MockFirebaseAuth();
final user = auth.currentUser;
expect(user, isNull);
});
});
}

Related

How to test a ValueNotifier value from a stream?

Problem
I'm developing a simple Todo app and trying to create test for my files before I develop the UI.
I created a repository which exposes a Stream<List<Todo>>> and I'm listening to it in the TodosOverviewStore. I tried to test if the Store.value would update when the repository stream emitted a new value, but I can't get it right.
Code
todo_repository_impl.dart
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../domain/entities/todo.dart';
import '../domain/repositories/todo_repository.dart';
class TodoRepositoryImpl implements TodoRepository {
final SharedPreferences _prefs;
#visibleForTesting
static const String todoKey = '__todo_key__';
TodoRepositoryImpl({required SharedPreferences prefs}) : _prefs = prefs {
_init();
}
final _controller = StreamController<List<Todo>>();
void _init() {
final result = _prefs.getString(todoKey);
if (result == null || result.isEmpty) return _controller.add([]);
final todos = jsonDecode(result).map((e) => Todo.fromMap(e)).toList();
return _controller.add(todos);
}
#override
Stream<List<Todo>> getTodos() => _controller.stream;
}
todos_overview_store.dart
import 'dart:async';
import 'package:flutter/material.dart';
import '../../domain/entities/todo.dart';
import '../../domain/repositories/todo_repository.dart';
class TodosOverviewStore extends ValueNotifier<List<Todo>> {
final TodoRepository _repository;
late final StreamSubscription<List<Todo>> _subscription;
TodosOverviewStore({required TodoRepository todoRepository})
: _repository = todoRepository,
super([]);
void subscriptionRequested() {
_subscription = _repository.getTodos().listen((event) => value = event);
}
#override
Future<void> dispose() async {
await _subscription.cancel();
super.dispose();
}
}
todos_overview_store_test.dart
import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'package:hiveleak/domain/entities/todo.dart';
import 'package:hiveleak/domain/repositories/todo_repository.dart';
import 'package:hiveleak/presentation/stores/todos_overview_store.dart';
import 'package:mocktail/mocktail.dart';
class TodoRepositoryMock extends Mock implements TodoRepository {}
main() {
final todoRepository = TodoRepositoryMock();
late TodosOverviewStore todosOverviewStore;
final todo = Todo(title: 'lorem ipsum', done: false);
group('subscriptionRequested', () {
when(() => todoRepository.getTodos())
.thenAnswer((_) => Stream.value([todo]));
setUp(() {
todosOverviewStore = TodosOverviewStore(todoRepository: todoRepository);
});
test('It should call todoRepository.getTodos', () {
todosOverviewStore.subscriptionRequested();
verify(() => todoRepository.getTodos()).called(1);
});
test('It should update its value when stream emits', () {
todosOverviewStore.subscriptionRequested();
expect(todosOverviewStore.value, equals([todo]));
});
});
}
Error
But when I run this test, I get the following result:
package:test_api expect
package:flutter_test/src/widget_tester.dart 460:16 expect
test\presentation\stores\todos_overview_store_test.dart 34:7 main.<fn>.<fn>
Expected: [Instance of 'Todo']
Actual: []
Which: at location [0] is [] which shorter than expected
What should I do to make this work ? Thanks in advance.

A value of type List<dynamic> can't be returned from this function 'contacts' because it has a return type of List<Contact>?

I am using the dependency flutter_contacts for this code and this is for a provider file. Here is the code below :
import 'package:provider/provider.dart';
import 'main.dart';
import 'star.dart';
import 'package:flutter_contacts/flutter_contacts.dart';
class PRProvider extends ChangeNotifier {
final List<Contact>? _fivestar = [];
List<Contact>? get contacts =>
_fivestar.map((id) => contacts.getById(id)).toList();
}

Flutter mocktail get error when put mock getx controller

I have this getx controller :
class CustomerPOAutocompleteState extends GetxController {
CustomerPOAutocompleteState();
...
Future<void> getCustomer(String title, String? propertyId) async {
var result = await RRGraphQL().artemis!...
_customers =...
update(['update']);
}
Now by Mock mocktail I created a mock class:
class MockController extends Mock implements CustomerPOAutocompleteState {}
When I try to put it I got error:
void main() {
late MockController mockController;
setUpAll(() {
mockController = MockController();
});
...
testWidgets('test', (WidgetTester tester) async {
Get.put<CustomerPOAutocompleteState>(mockController,tag: "");
error:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following _TypeError was thrown running a test:
type 'Null' is not a subtype of type 'InternalFinalCallback<void>'
UPDATED Answer
This error occurs since Get.put performs calls on your GetxController which have not been mocked out correctly.
You can either do this manually (you will have to check the implementation details of Get.put and GetxController). Or you can do, what the Get documentation suggests and let your mock extend GetxController and use Mock as a mixin.
class MockController extends GetxController
with Mock
implements CustomerPOAutocompleteState {}
Check out this full example:
import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart';
import 'package:mocktail/mocktail.dart';
class DemoController extends GetxController {
var count = 0.obs;
increment() => count++;
}
class MockController extends GetxController
with Mock
implements DemoController {}
main() {
late MockController mockController;
setUpAll(() {
mockController = MockController();
});
test('GetX Test', () {
when(() => mockController.count).thenAnswer((_) => 12.obs);
Get.put<DemoController>(mockController, tag: "");
mockController.increment();
expect(mockController.count.value, 12);
});
}

The argument type 'Future<UserCredential>' can't be assigned to the parameter type 'dynamic Function()'

I am learning about TDD and practicing my test writing. I want to write a test for my login through Firebase.
here is the test file:
import 'package:firebase/firebase.dart';
import 'package:firebase_auth/firebase_auth.dart' as fa;
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:scopetik/features/login/data/login_data_impl.dart';
import 'package:scopetik/features/login/models/user_model.dart';
class MockFirebaseAuth extends Mock implements fa.FirebaseAuth {}
class MockFirebaseUser extends Mock implements fa.User {}
class MockAuthResult extends Mock implements fa.UserCredential {}
void main() {
late LoginDataImpl sut;
late MockFirebaseAuth mockFirebaseAuth;
setUp(() {
mockFirebaseAuth = MockFirebaseAuth();
sut = LoginDataImpl(mockFirebaseAuth);
});
group(
'Test LoginDataImpl class',
() {
when(mockFirebaseAuth.signInWithEmailAndPassword(
email: 'email', password: 'password'))
.thenAnswer((_) async {
return MockAuthResult();
});
test(
"get UserModel",
() async {
//arrange
},
);
},
);
}
I don't know why the when function won't let me return a future<UserCredential>.
I also had the same problem. You need to use mockito instead of mocktail in order to do that.
You can find when property of both libraries here, mocktail, mockito

How to access another class from a different file in the same flutter project?

Hello everyone please i just started learning and working on flutter some few months ago,i am now trying my hands on it.
I want to know if there is a way that will enable me to access the class Position in the main.dart from the request.dart in such that the part where i add my api in the Uri.parse() the ${postion.latitude} and${position.longitude} won't be Undefined and refer to the Position class in the main.dart file. Thank you!
main.dart file
'''
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:provider/provider.dart';
import 'package:rider_app/AllScreens/searchScreen.dart';
import 'package:rider_app/AllWidgets/Divider.dart';
import 'package:rider_app/Assistants/assistantMethods.dart';
import 'package:rider_app/DataHandler/appData.dart';
class MainScreen extends StatefulWidget
{
static const String idScreen = "mainScreen";
const MainScreen({Key key}) : super(key: key);
#override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen>
{
Completer<GoogleMapController> _controllerGoogleMap = Completer();
GoogleMapController newGoogleMapController;
GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
Position currentPosition;
var geoLocator = Geolocator();
double bottomPaddingOfMap=0;
void locatePosition() async
{
Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
currentPosition= position;
LatLng latLatPosition = LatLng(position.latitude, position.longitude);
//Camera move
CameraPosition cameraPosition = new CameraPosition(target: latLatPosition, zoom: 16);
newGoogleMapController.animateCamera(CameraUpdate.newCameraPosition(cameraPosition));
//newGoogleMapController.animateCamera(CameraUpdate.newCameraPosition(cameraPosition));
String address = await AssistantMethods.searchCoordinateAddress(position, context);
}
'''
request.dart file
'''
import 'dart:convert';
import 'dart:html';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:geolocator/geolocator.dart';
import 'package:http/http.dart' as http;
import 'package:rider_app/configMaps.dart';
import 'package:rider_app/lib/AllScreens/mainscreen.dart';
class RequestAssistant
{
static Future<dynamic> getRequest(url) async
{
var url = Uri.parse("https://maps.googleapis.com/maps/api/geocode/json?latlng=${position.latitude},${position.longitude}&key=$mapKey");
http.Response response = await http.get(url);
try
{
if(response.statusCode==200)
{
String jSonData = response.body;
var decodeData = jsonDecode(jSonData);
return decodeData;
}
else
{
return "failed";
}
}
catch(exp)
{
return "failed";
}
}
}'''
You can pass in getRequest method life
getRequest(Position position) async {...}