LateInitializationError: Field has not been initialized in flutter unit test - flutter

When I run the unit test, I get the error "LateInitializationError: Field 'currentBsTestLocizJson' has not been initialized."
Here is my unit test code
class MockLociz extends Mock implements Lociz{
Map<String, dynamic> currentBsTestLocizJson = {
"verbal_memory_test":"verbal_memory_test",
"tap_words_remember":"tap_words_remember"
};
}
void main() {
late MockLociz mockLociz;
const tTestId = 1;
const tSampleString = "hello world";
setUp(() {
mockLociz = MockLociz();
});
group('get next test screen', () {
test('should return TestTitleAndQATypeParams type object when correct test id is passed',
() async {
// Arrange
// Act
final result = failedTestName(tTestId);
// Assert
expect(result, equals('verbal_memory_test'));
});
});
}
Here is the original Locaize class
class Lociz {
static final Lociz _singleton = new Lociz._internal();
Lociz._internal();
static Lociz get instance => _singleton;
bool locizJsonInitialized = false;
late Map<String, dynamic> currentAthleteLocizJson;
late Map<String, dynamic> currentBsTestLocizJson;
late Map<String, dynamic> currentCommonLocizJson;
}

Related

How to write exception in build of AsyncNotifier from riverpod

When not connected to the internet, executing the following code will cause a _ClientSocketException.
How should I write the exception handling?
class AsyncTodosNotifier extends AsyncNotifier<List<Todo>> {
Future<List<Todo>> _fetchTodo() async {
final json = await http.get('api/todos'); //** _ClientSocketException Error occurred**
final todos = jsonDecode(json) as List<Map<String, dynamic>>;
return todos.map((todo) => Todo.fromJson(todo)).toList();
}
#override
Future<List<Todo>> build() async {
return _fetchTodo();
}
Using the AsyncNotifier's build() from riverpod, I would like to code exception handling with AsyncValue.guard, but it results in a syntax error.
How should I write it to make it work?
When trying to get json data, if I can't connect to the internet, I want to write exception handling so that it doesn't abort.
Reference:
https://docs-v2.riverpod.dev/docs/providers/notifier_provider
full code:
implementation.
#immutable
class Todo {
const Todo({
required this.id,
required this.description,
required this.completed,
});
factory Todo.fromJson(Map<String, dynamic> map) {
return Todo(
id: map['id'] as String,
description: map['description'] as String,
completed: map['completed'] as bool,
);
}
final String id;
final String description;
final bool completed;
Map<String, dynamic> toJson() => <String, dynamic>{
'id': id,
'description': description,
'completed': completed,
};
}
class AsyncTodosNotifier extends AsyncNotifier<List<Todo>> {
Future<List<Todo>> _fetchTodo() async {
final json = await http.get('api/todos'); //** _ClientSocketException Error occurred**
final todos = jsonDecode(json) as List<Map<String, dynamic>>;
return todos.map((todo) => Todo.fromJson(todo)).toList();
}
#override
Future<List<Todo>> build() async {
return _fetchTodo();
}
Future<void> addTodo(Todo todo) async {
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
await http.post('api/todos', todo.toJson());
return _fetchTodo();
});
}
}
final asyncTodosProvider =
AsyncNotifierProvider<AsyncTodosNotifier, List<Todo>>(() {
return AsyncTodosNotifier();
});

How to get Single document from firestore and call the fields in UI in flutter/dart

Here is my attempt
In my Controller I have this
class UserController extends GetxController {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
var _proo;
get prooo => _proo;
Future<Member?> readProfile() async {
_proo = FireStoreHelper().fFetch("users", "user1");
}
}
In my FireStoreHelper I have this
class FireStoreHelper {
fFetch(collection, doc) {
final docMember =
FirebaseFirestore.instance.collection(collection).doc(doc);
var query = docMember.get();
return query;
}
This is my Model
class Member {
final String? username;
//...others
Member({
this.username,
//...others
});
static Member fromJson(Map<String, dynamic> json) => Member(
username: json['username'],
//...others
);
}
Then in my UI I have this
Get.lazyPut(() => UserController().readProfile());
return GetBuilder<UserController>(builder: (userController) {
//.......
Text(userController.prooo.username),
}
Actually what am trying get a username of user1 as seen in the Image below
Please help me, I am new to this.
try this one...
fFetch(collection, doc) async {
final docMember = await
FirebaseFirestore.instance.collection(collection).doc(doc).get();
return docMember;
}
static Future<Member?> readProfile() async {
_proo = await FireStoreHelper().fFetch("users", "user1");
Member member = Member.fromJson(_proo);
return member;
}

Error fetching API / A value of type 'List<Heroes>' can't be returned from the method 'getHeroes' because has a return type of 'Future<List<String>?>

im new in Dart/Flutter and im struggling with consuming API, here is my file thats inside my model folder:
List<Heroes> heroesFromJson(String str) =>
List<Heroes>.from(json.decode(str).map((x) => Heroes.fromJson(x)));
String heroesToJson(List<Heroes> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Heroes {
Heroes({
required this.id,
required this.name,
required this.localizedName,
required this.primaryAttr,
required this.attackType,
required this.roles,
});
int id;
String name;
String localizedName;
String primaryAttr;
String attackType;
List<String> roles;
factory Heroes.fromJson(Map<String, dynamic> json) => Heroes(
id: json["id"],
name: json["name"],
localizedName: json["localized_name"],
primaryAttr: json["primary_attr"],
attackType: json["attack_type"],
roles: List<String>.from(json["roles"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"localized_name": localizedName,
"primary_attr": primaryAttr,
"attack_type": attackType,
"roles": List<dynamic>.from(roles.map((x) => x)),
};
}
And here is where im getting the error, inside services folder:
class DotaServices {
Future<List<String>?> getHeroes() async {
var client = http.Client();
var url = Uri.parse('https://api.opendota.com/api/heroes');
var response = await client.get(url);
if (response.statusCode == 200) {
var json = response.body;
return heroesFromJson(json);
}
}
}
The error is occuring in that line:
return heroesFromJson(json);
And the message that appears is:
A value of type 'List<Heroes>' can't be returned from the method 'getHeroes' because it has a return type of 'Future<List<String>?>'.
how to solve it? Im struggling real hard on this :/
Your method returns a list of heroes... so... you need to return a list of heroes:
Future<List<String>?> getHeroes() async {
needs to be
Future<List<Heroes>?> getHeroes() async {
heroesFromJson returns a list of heroes so getHeroes has to return a list of heroes:
Future<List<Heroes>?> getHeroes()
Also, your method heroesFromJson returns a List<Heroes> not nullable, but your method getHeroes() return a List<Heroe>? which is nullable.
You either can make your return from heroesFromJson a nullable list List<T>? or your return from getHeroes() a non-nullable list List
Be careful making your List nullable or non-nullable List<Hero>?, not your Hero List<Hero?>
It seems to me that such code should work more reliably.
return Hero.fromJsonList(json as List);
This small example (including function main) was generated with a very small script.
import 'dart:convert';
import 'package:http/http.dart' as http;
void main(List<String> args) async {
final svc = DotaServices();
final heroes = await svc.getHeroes();
print('Heroes: ${heroes.length}');
}
class DotaServices {
Future<List<Hero>> getHeroes() async {
final client = http.Client();
final url = Uri.parse('https://api.opendota.com/api/heroes');
final response = await client.get(url);
if (response.statusCode == 200) {
final source = response.body;
final json = jsonDecode(source);
return Hero.fromJsonList(json as List);
}
throw StateError('Http error: ${response.statusCode}');
}
}
class Hero {
Hero(
{required this.id,
required this.name,
required this.localizedName,
required this.primaryAttr,
required this.attackType,
required this.roles});
factory Hero.fromJson(Map json) {
return Hero(
id: json['id'] as int,
name: json['name'] as String,
localizedName: json['localized_name'] as String,
primaryAttr: json['primary_attr'] as String,
attackType: json['attack_type'] as String,
roles: json['roles'] == null
? []
: (json['roles'] as List).map((e) => e as String).toList(),
);
}
final int id;
final String name;
final String localizedName;
final String primaryAttr;
final String attackType;
final List<String> roles;
static List<Hero> fromJsonList(List json) {
return json.map((e) => Hero.fromJson(e as Map)).toList();
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'localized_name': localizedName,
'primary_attr': primaryAttr,
'attack_type': attackType,
'roles': roles,
};
}
static List<Map<String, dynamic>> toJsonList(List<Hero> list) {
return list.map((e) => e.toJson()).toList();
}
}
Using this codegen script you can generate the models and serializers.
It also generates a working example.
import 'dart:io';
import 'package:object_serializer/json_serializer_generator.dart';
import 'package:yaml/yaml.dart';
void main() {
final classes = loadYaml(_classes) as Map;
final g = JsonSerializerGenerator();
final classesCode = g.generateClasses(classes);
final values = {
'classes': classesCode,
};
var source = g.render(_template, values);
source = g.format(source);
File('bin/stackoverflow.dart').writeAsStringSync(source);
}
const _classes = '''
Hero:
fields:
id: int
name: String
localizedName: {type: String, alias: localized_name}
primaryAttr: {type: String, alias: primary_attr}
attackType: {type: String, alias: attack_type}
roles: List<String>
''';
const _template = r'''
import 'dart:convert';
import 'package:http/http.dart' as http;
void main(List<String> args) async {
final svc = DotaServices();
final heroes = await svc.getHeroes();
print('Heroes: ${heroes.length}');
}
class DotaServices {
Future<List<Hero>> getHeroes() async {
final client = http.Client();
final url = Uri.parse('https://api.opendota.com/api/heroes');
final response = await client.get(url);
if (response.statusCode == 200) {
final source = response.body;
final json = jsonDecode(source);
return Hero.fromJsonList(json as List);
}
throw StateError('Http error: ${response.statusCode}');
}
}
{{classes}}
''';

type '_CompactLinkedHashSet<String>' is not a subtype of type 'Map<dynamic, dynamic>?'

I'm following a tutorial that builds a messaging app using flutter and rethinkdb. It hasn't been updated for null safety, but I'm trying to move forward and learn it with the most updated packages & latest version of flutter as I go, as a beginner.
I'm trying to test typing notifications, and I'm getting an error that I can't decipher.
type '_CompactLinkedHashSet<String>' is not a subtype of type 'Map<dynamic, dynamic>?'
package:rethink_db_ns/src/ast.dart:1223
TypingNotification.send
package:chat/…/typing/typing_notification.dart:22
main.<fn>
test/typing_notification_test.dart:44
main.<fn>
test/typing_notification_test.dart:37
All of the Maps that I have are Map<String, dynamic>, so I'm not sure where the Map<dynamic, dynamic> is coming from. I am also using package:rethink_db_ns instead of what the tutorial author uses, which is the rethink package before ns was added. So I'm not sure if I have to change things further for the new package. I also made sure I didn't see any red squiggles before I tried running the test.
Here are my files:
Here is the testing file where I try to run the test and get the aforementioned error:
import 'package:chat/src/models/typing_event.dart';
import 'package:chat/src/models/user.dart';
import 'package:chat/src/services/typing/typing_notification.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:rethink_db_ns/rethink_db_ns.dart';
import 'helpers.dart';
void main() {
RethinkDb r = RethinkDb();
late Connection connection;
late TypingNotification sut;
setUp(() async {
connection = await r.connect();
await createDb(r, connection);
sut = TypingNotification(r, connection);
});
tearDown(() async {
sut.dispose();
await cleanDb(r, connection);
});
final user = User.fromJson({
'id': '1234',
'active': true,
'lastSeen': DateTime.now(),
});
final user2 = User.fromJson({
'id': '1111',
'active': true,
'lastSeen': DateTime.now(),
});
test('sent typing notification successfully', () async {
TypingEvent typingEvent = TypingEvent(
from: user2.id!,
to: user.id!,
event: Typing.start,
);
final res = await sut.send(event: typingEvent, to: user);
expect(res, true);
});
}
Here is typing_notification.dart:
import 'dart:async';
import 'package:chat/src/models/user.dart';
import 'package:chat/src/models/typing_event.dart';
import 'package:chat/src/services/typing/typing_notification_service_contract.dart';
import 'package:rethink_db_ns/rethink_db_ns.dart';
class TypingNotification implements ITypingNotification {
final Connection _connection;
final RethinkDb _r;
final _controller = StreamController<TypingEvent>.broadcast();
StreamSubscription? _changefeed; // added ? to this
TypingNotification(this._r, this._connection); //added this._change
#override
Future<bool> send({required TypingEvent event, required User to}) async {
if (!to.active) return false;
Map record = await _r
.table('typing_events')
.insert(event.toJson(), {'conflict:' 'update'}).run(_connection);
return record['inserted'] == 1;
}
#override
Stream<TypingEvent> subscribe(User user, List<String> userIds) {
_startReceivingTypingEvents(user, userIds);
return _controller.stream;
}
#override
void dispose() {
_changefeed?.cancel();
_controller.close();
}
_startReceivingTypingEvents(User user, List<String> userIds) {
_changefeed = _r
.table('typing_events')
.filter((event) {
return event('to')
.eq(user.id)
.and(_r.expr(userIds).contains(event('from')));
})
.changes({'include_initial': true})
.run(_connection)
.asStream()
.cast<Feed>()
.listen((event) {
event
.forEach((feedData) {
if (feedData['new_val'] == null) return;
final typing = _eventFromFeed(feedData);
_controller.sink.add(typing);
_removeEvent(typing);
})
.catchError((err) => print(err))
.onError((error, stackTrace) => print(error));
});
}
TypingEvent _eventFromFeed(feedData) {
return TypingEvent.fromJson(feedData['new_val']);
}
_removeEvent(TypingEvent event) {
_r
.table('typing_events')
.get(event.id)
.delete({'return_changes': false}).run(_connection);
}
}
Here is typing_event.dart:
enum Typing { start, stop }
extension TypingParser on Typing {
String value() {
return toString().split('.').last;
}
static Typing fromString(String event) {
return Typing.values.firstWhere((element) => element.value() == event);
}
}
class TypingEvent {
final String from;
final String to;
final Typing event;
String? _id;
String? get id => _id;
TypingEvent({
required this.from,
required this.to,
required this.event,
});
Map<String, dynamic> toJson() => {
'from': this.from,
'to': this.to,
'event': this.event.value(),
};
factory TypingEvent.fromJson(Map<String, dynamic> json) {
var event = TypingEvent(
from: json['from'],
to: json['to'],
event: TypingParser.fromString(json['event']),
);
event._id = json['id'];
return event;
}
}
And here is typing_notification_service_contract.dart:
import 'package:chat/src/models/typing_event.dart';
import 'package:chat/src/models/user.dart';
abstract class ITypingNotification {
Future<bool> send(
{required TypingEvent event, required User to}); // the tutorial did not include ", required User to" but I added it to prevent an error, since required User to is passed in another file
Stream<TypingEvent> subscribe(User user, List<String> userIds);
void dispose();
}
And finally, typing_event.dart
enum Typing { start, stop }
extension TypingParser on Typing {
String value() {
return toString().split('.').last;
}
static Typing fromString(String event) {
return Typing.values.firstWhere((element) => element.value() == event);
}
}
class TypingEvent {
final String from;
final String to;
final Typing event;
String? _id;
String? get id => _id;
TypingEvent({
required this.from,
required this.to,
required this.event,
});
Map<String, dynamic> toJson() => {
'from': this.from,
'to': this.to,
'event': this.event.value(),
};
factory TypingEvent.fromJson(Map<String, dynamic> json) {
var event = TypingEvent(
from: json['from'],
to: json['to'],
event: TypingParser.fromString(json['event']),
);
event._id = json['id'];
return event;
}
}
I'm a total beginner & trying to push myself to learn null safety, so there is a good chance my error is very simple and I'm just not seeing it. Can anyone point me in the right direction or offer any guidance here? I can also add more details upon request if you think it might be helpful.
Try replacing
.insert(event.toJson(), {'conflict:' 'update'}).run(_connection);
with
.insert(event.toJson(), {'conflict': 'update'}).run(_connection);
^
add colon
in typing_notification,.dart line 22, it's expecting Map, probably you meant to place ":" outside the string

How can I get data using provider?

I am implementing login with provider but I am not getting data on dashboard page.
Model Class
class LoginModel {
Data data;
int status;
String message;
LoginModel({this.data, this.status, this.message});
LoginModel.fromJson(Map<String, dynamic> json) {
data = json['data'] != null ? new Data.fromJson(json['data']) : null;
status = json['status'];
message = json['message'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.data != null) {
data['data'] = this.data.toJson();
}
data['status'] = this.status;
data['message'] = this.message;
return data;
}
}
class Data {
String customerId;
String customerMobileNo;
String customerToken;
String otp;
Data({this.customerId, this.customerMobileNo, this.customerToken, this.otp});
Data.fromJson(Map<String, dynamic> json) {
customerId = json['customerId'];
customerMobileNo = json['customerMobileNo'];
customerToken = json['customerToken'];
otp = json['otp'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['customerId'] = this.customerId;
data['customerMobileNo'] = this.customerMobileNo;
data['customerToken'] = this.customerToken;
data['otp'] = this.otp;
return data;
}
}
Provider Class
class AuthProvider extends ChangeNotifier {
Future<LoginModel> generateOTP(String mobileNumber) async {
var result;
Response response = await post(
AppUrl.login,
body: {
'mobileNo': mobileNumber,
},
);
if(response.statusCode==200) {
final responseData = json.decode(response.body);
var userData = responseData['data'];
print(responseData);
LoginModel authUser = LoginModel.fromJson(userData);
notifyListeners();
}
else {
print("Something went wrong");
}
return result;
}
}
Display Page
class Dashboard extends StatelessWidget {
#override
Widget build(BuildContext context) {
final userTest = Provider.of<AuthProvider>(context);
return Scaffold(
body: Center(
child: ListView(
shrinkWrap: true,
children: [
Text(userTest.authUser.data.customerToken),
],
),
),
);
}
Error
The following NoSuchMethodError was thrown while handling a gesture:
The getter 'customerToken' was called on null.
Receiver: null
Tried calling: customerToken
How can I access the property of LoginModel class. Can anyone solve my query please help me, I tried a lott but I can not get value.
You cannot notify your listeners with normal Future functions (though, I am not sure because you didn't provide the full code of your provider class). You will have to put your generateOTP() function in a changenotifier class that will help you to notify your listeners whenever required and make it scoped to your widget.
You are getting this error because you are not storing your token anywhere or you are not invoking your storage token before using it. So first, please try to store your token and invoke it before using it.
LoginModel authUser = LoginModel.fromJson(userData); you are initializing value to method variable LoginModel authUser not a class variable authUser try removing LoginModel from before 'authUser'.
In Dashboard you should also check for null value, you can do that like this userTest?.authUser?.data?.customerToken ?? ''