Not able to print debug message while unit testing in Flutter - flutter

I am testing a pretty straightforward use-case in Flutter. Inside the use-case class, I have a function that I'm invoking from my test. And I want to add some debug print statements to print the value of some variables inside the function of use-case. But it's not getting printed anywhere. How can I achieve this?
The function in Use-case.
Future<Either<Failure, List<Contest>>> call(NoParams params) async {
final result = await repository.getAllContests();
final currentDateTime = DateTime.now();
List<Contest> ongoingContests = [];
result.fold(
(l) => throw ServerException(),
(allContestList) => () {
for (var contest in allContestList) {
var contestStartTime = DateTime.parse(contest.start_time);
var contestEndTime = DateTime.parse(contest.end_time);
print(contestEndTime); //print statement
}
});
return Right(ongoingContests);
}
}
The test function
test('Should return only the ongoing contests', () async {
when(mockHomepageRepository.getAllContests()).thenAnswer((_) async =>
const Right([tContest, tOngoingContest, tUpcomingContest]));
final result = await getOngoingContests(NoParams()); //invoking the function
expect(result, const Right([tOngoingContest]));
verify(mockHomepageRepository.getAllContests());
verifyNoMoreInteractions(MockHomepageRepository());
});

Related

Flutter how to create package with function

I'm trying to make a package. I need to use async function, but I can't use it while building package.
Package Code:
class Sozluk {
wiki(ceviri) async {
var res = await http.Client()
.get(Uri.parse('https://sozluk.gov.tr/gts?ara=$ceviri'));
var body = res.body;
var decoded = jsonDecode(body);
var json = decoded[0];
var sozlukanlam = json["anlamlarListe"][0]["anlam"];
print(sozlukanlam);
return sozlukanlam;
}
}
Test Code:
void main() {
test('köpek', () {
final sozluk = Sozluk();
var cevap = sozluk.wiki('köpek');
print(cevap);
});
}
The print I got:
Instance of 'Future<dynamic>'
You code is missing a lot of pieces. Just because Dart allows you to write code like a sloppy web developer, does not mean you should. Dart is strongly typed, that is an advantage, please use it.
Problems:
ceviri has no explicit type.
wiki has no explicit return type.
wiki is not awaited
Your anonymous method is not async.
More information about Futures, async and await: What is a Future and how do I use it?
Fixing your code as good as possible:
class Sozluk {
Future<TYPE_X> wiki(TYPE_Y ceviri) async {
var res = await http.Client()
.get(Uri.parse('https://sozluk.gov.tr/gts?ara=$ceviri'));
var body = res.body;
var decoded = jsonDecode(body);
var json = decoded[0];
var sozlukanlam = json["anlamlarListe"][0]["anlam"];
print(sozlukanlam);
return sozlukanlam;
}
}
Test Code:
void main() {
test('köpek', () async {
final sozluk = Sozluk();
var cevap = await sozluk.wiki('köpek');
print(cevap);
});
}
Please note that you need to fill in TYPE_X and TYPE_Y, I have no idea which datatypes best represent your data. Is it a number? A text? You decide.
Yout question is unclear.
If you need to print
sozlukanlam
var in test function you need to await your wiki function becaus it is async.
So you could do somthing like that:
void main() {
test('köpek', () async {
final sozluk = Sozluk();
var cevap = await sozluk.wiki('köpek');
print(cevap);
});
}
OR, if test function couldn't bee async
void main() {
test('köpek', () {
final sozluk = Sozluk();
sozluk.wiki('köpek').then((sozlukanlam)=>print(cevap));
});
}

Exception in json.decode : Closure: () => String from Function 'toString'

I am getting some data from API in flutter. I am trying to decode the data using json.decode() but this decode function gives me the following error:
Closure: () => String from Function 'toString'
Here's my code:
Future<Product> createOrder() async {
var client = new http.Client();
var productModel = null;
try {
var response = await client
.get(Uri.https('butterbasket.onrender.com', Strings.createOrderUrl));
if (response.statusCode == 200) {
var body = response.body;
print("Body: $body");
var jsonMap = json.decode(body);
var productModel = Product.fromJson(jsonMap);
}
} catch (e) {
print("Exception: ${e.toString}");
}
return productModel;
}
Here is the Error Debug Console:
You are running into issues because the data you are loading in is an array, but the model is an object. You'll need to do something like the following:
final List jsonProducts = json.decode(body)
final List<Product> products =
jsonProducts.map((jsonProduct) => Product.fromJson(jsonProduct)).toList();
and then if you only need the first item you can do:
final Product product = products[0]
But don't forget to check if the array is big enough.
Your Future function must return an optional Product?, otherwise your future will never find a result as you are declaring it inside the function.
Instead of:
Future<Product> createOrder() async {}
Use:
Future<Product?> createOrder() async {}
Finally your async snapshot and FutureBuilder type should be of type <Product?>.

type 'Future<List<Appointment>>' is not a subtype of type 'List<Appointment>' in type cast

The error should be clear but I'm unsure how to go around it.
Basically I have a Stream builder I'm calling every second by getData() method to update my SfCalendar with new data.
Stream<DataSource> getData() async* {
await Future.delayed(const Duration(seconds: 1)); //Mock delay
List<Appointment> appointments = foo() as List<Appointment>;
List<CalendarResource> resources = bar() as List<CalendarResource>;
DataSource data = DataSource(appointments, resources);
print("Fetched Data");
yield data;
}
But my appointments method foo() is of type Future<List> and not List.
Future<List<Appointment>> foo() async {
var url0 = Uri.https(
"uri",
"/profiles.json");
List<Appointment> appointments = [];
try {
final response = await dio.get(url0.toString());
//final Random random = Random();
//_colorCollection[random.nextInt(9)];
response.data.forEach((key, value) {
appointments.add(
Appointment(
id: int.parse(
value["id"],
),
startTime: DateTime.parse(value["startTime"]),
endTime: DateTime.parse(value["endTime"]),
),
);
});
} catch (error) {
print(error);
}
return appointments;
}
That is what the error should be telling, yes?
I tried removing the Future cast from foo() appointments but then I can't use async.
I also tried returning Future.value(appointments) but same error.
This is where I call my Stream in initState():
#override
void initState() {
super.initState();
print("Creating a sample stream...");
Stream<DataSource> stream = getData();
print("Created the stream");
stream.listen((data) {
print("DataReceived");
}, onDone: () {
print("Task Done");
}, onError: (error) {
print(error);
});
print("code controller is here");
}
Thank you, please help when possible
Just like JavaScript, async functions always return a Future. That's why you can't use async when you remove Future from the return type.
Since you're not waiting for that Future to resolve, you're actually trying to cast a Future to a List, which isn't a valid cast. All you should need to do is wait for the function to finish so it resolves to a List:
List<Appointment> appointments = await foo() as List<Appointment>;
and, since your return type is Future<List<Appointment>>, you don't actually need to cast the result.
List<Appointment> appointments = await foo();

Is it possible to filter a List with a function that returns Future?

I have a list List<Item> list and a function Future<bool> myFilter(Item).
Is there a way to filter my list using the Future returning function myFilter()?
The idea is to be able to do something like this:
final result = list.where((item) => myFilter(item)).toList();
But this is not possible since where expects bool and not Future<bool>
Since the iteration involves async operation, you need to use a Future to perform the iteration.
final result = <Item>[];
await Future.forEach(list, (Item item) async {
if (await myFilter(item)) {
result.add(item);
}
});
You can iterate over your collection and asynchronously map your value to the nullable version of itself. In asyncMap method of Stream class you can call async methods and get an unwrapped Future value downstream.
final filteredList = await Stream.fromIterable(list).asyncMap((item) async {
if (await myFilter(item)) {
return item;
} else {
return null;
}
}).where((item) => item != null).toList()
You can try bellow:
1, Convert List => Stream:
example:
Stream.fromIterable([12, 23, 45, 40])
2, Create Future List with this function
Future<List<int>> whereAsync(Stream<int> stream) async {
List<int> results = [];
await for (var data in stream) {
bool valid = await myFilter(data);
if (valid) {
results.add(data);
}
}
return results;
}
Here's a complete solution to create a whereAsync() extension function using ideas from the accepted answer above. No need to convert to streams.
extension IterableExtension<E> on Iterable<E> {
Future<Iterable<E>> whereAsync(Future<bool> Function(E element) test) async {
final result = <E>[];
await Future.forEach(this, (E item) async {
if (await test(item)) {
result.add(item);
}
});
return result;
}
}
You can now use it in fluent-style on any iterable type. (Assume the function validate() is an async function defined elsewhere):
final validItems = await [1, 2, 3]
.map((i) => 'Test $i')
.whereAsync((s) async => await validate(s));
Try this:
final result = turnOffTime.map((item) {
if(myFilter(item)) {
return item;
}
}).toList();

Simultaneous dynamic async calls

I have a dynamic list of strings including codes.
I want to fetch events for each code and then yield to next state.
I have tried Future.wait() but since is dynamic I can not pass a list of async calls.
This is my code so far:
var packagesData = List<BuiltList<Event>>();
for (var packageNumber in packages) {
final packageEvents = await serviceDataSource.fetchPackageEvents(packageNumber);
packagesData.add(packageEvents);
if (packagesData.length == packages.length) {
return persistAllPackagesData(packagesData);
}
}
I wanted to do something similar to a Promise:
Promise.all([
// for loop here
]).then(() => {
console.log('I did everything!');
});
Use a taskList to maintain needed task and use Future.wait
List<Future<int>> taskList = [];
taskList.add(getRandomNumber());
...
Future.wait(taskList)
.then
full code
import 'dart:async';
import 'dart:math';
Future<int> getRandomNumber() async {
var random = new Random();
return random.nextInt(100);
}
void findSmallestNumberInList(List<int> lst) {
print("all numbers are in:");
lst.forEach((l) => print(l));
lst.sort();
int largest = lst.first;
print("The smallest random # we generated was: ${largest}");
}
void main() async {
List<Future<int>> taskList = [];
taskList.add(getRandomNumber());
taskList.add(getRandomNumber());
taskList.add(getRandomNumber());
Future.wait(taskList)
.then((List<int> results) => findSmallestNumberInList(results));
Future.wait([getRandomNumber(), getRandomNumber(), getRandomNumber()])
.then((List<int> results) => findSmallestNumberInList(results));
}