Cannot mock a method for multiple invocation with Returns - nsubstitute

I am trying to mock a method which takes two parameters int and out parameter of bool. I am able to set it up correctly for the first time invocation and it returns the right out value and return value. However, when trying to invoke the same method for the second time it is not invoking my delegate. Any idea what is wrong here:
What I tried:
mock.GetRows(Arg.Is<int>(10), out moreRows).Returns(x =>
{
if (first)
{
first = false;
x[1] = true;
return new object[][] { new object[] { null, "Collêction Namê" }, new object[] { null, "Collêction Name" }, new object[] { null, "COllection Name" } };
}
else
{
x[1] = false;
return new object[][] { new object[] { collectionId, "Collection Name" } };
}
});
I tried this as well:
mock.GetRows(Arg.Is<int>(10), out moreRows).Returns(
x =>
{
first = false;
x[1] = true;
return new object[][] { new object[] { null, "Collêction Namê" }, new object[] { null, "Collêction Name" }, new object[] { null, "COllection Name" } };
},
x=>
{
x[1] = false;
return new object[][] { new object[] { collectionId, "Collection Name" } };
});
This works however:
.ReturnsForAnyArgs(x =>
{
if (first)
{
first = false;
x[1] = true;
return new object[][] { new object[] { null, "Collêction Namê" }, new object[] { null, "Collêction Name" }, new object[] { null, "COllection Name" } };
}
else
{
x[1] = false;
return new object[][] { new object[] { collectionId, "Collection Name" } };
}
});

The problem with mocking out parameters is that the value changes each call, so that the call initially stubbed with Returns is no longer matched.
You have correctly identified the workaround of using ReturnsForAnyArgs, as described in this answer.

Related

Custom directive to check the value of two or more fields

I tried my best to write a custom directive in Apollo Server Express to validate two input type fields.
But the code even works but the recording of the mutation already occurs.
I appreciate if anyone can help me fix any error in the code below.
This is just sample code, I need to test the value in two fields at the same time.
const { SchemaDirectiveVisitor } = require('apollo-server');
const { GraphQLScalarType, GraphQLNonNull, defaultFieldResolver } = require('graphql');
class RegexDirective extends SchemaDirectiveVisitor {
visitInputFieldDefinition(field) {
this.wrapType(field);
}
visitFieldDefinition(field) {
this.wrapType(field);
}
wrapType(field) {
const { resolve = defaultFieldResolver } = field;
field.resolve = async function (source, args, context, info) {
if (info.operation.operation === 'mutation') {
if (source[field.name] === 'error') {
throw new Error(`Find error: ${field.name}`);
}
}
return await resolve.call(this, source, args, context, info);
};
if (
field.type instanceof GraphQLNonNull
&& field.type.ofType instanceof GraphQLScalarType
) {
field.type = new GraphQLNonNull(
new RegexType(field.type.ofType),
);
} else if (field.type instanceof GraphQLScalarType) {
field.type = new RegexType(field.type);
} else {
// throw new Error(`Not a scalar type: ${field.type}`);
}
}
}
class RegexType extends GraphQLScalarType {
constructor(type) {
super({
name: 'RegexScalar',
serialize(value) {
return type.serialize(value);
},
parseValue(value) {
return type.parseValue(value);
},
parseLiteral(ast) {
const result = type.parseLiteral(ast);
return result;
},
});
}
}
module.exports = RegexDirective;

The argument type 'List<Categories>' can't be assigned to the parameter type 'Iterable<Categories>'

Here's my model class Categories
List<Categories> categoriesFromJson(String str) => List<Categories>.from(json.decode(str).map((x) => Categories.fromJson(x)));
String categoriesToJson(List<Categories> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Categories {
Categories({
this.id,
this.name,
this.parentId,
this.slug,
this.position,
this.status,
});
int id;
String name;
int parentId;
String slug;
int position;
int status;
factory Categories.fromJson(Map<String, dynamic> json) => Categories(
id: json["id"],
name: json["name"],
parentId: json["parent_id"],
slug: json["slug"],
position: json["position"],
status: json["status"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"parent_id": parentId,
"slug": slug,
"position": position,
"status": status,
};
}
my apiServices
static Future<List<Categories>> fetchCategories() async {
String url = "/categories/all";
var response = await http.get(BASE_URL + url);
if(response.statusCode == 200) {
return categoriesFromJson(response.body).toList();
} else {
return null;
}
}
api calling function in my controller
var categoryNames = <Categories>[].obs;
void fetchCategories() async {
try{
isLoading(true);
var res = await ApiServices.fetchCategories();
if(res !=null){
categoryNames.addAll(res);
}
}finally{
isLoading(false);
}
}
in the controller, while res in categoryNames.addAll(res) is underlined with red squizzy line and above error message is displayed. When i have used same type both for categoryNews and fetchCategories() of apiService, why i am having this error. Any help will be appreciated.
try to explictly define type like this
List<Categories> categoryNames = [];
also make sure to return a List from your .map() add .toList() to the end

Flutter Return API Value to FutureBuilder Null

I want to get data from API and convert it List to show it to Mobile, but FutureBuilder always said my data is null. I already print my data it has the data. But when I return it to FutureBuilder it just null.
API Example
{
"success": true,
"data": {
"current_page": 1,
"data": [
{
"absence_date": "2021-02-09",
"time_in": "07:51:34",
"time_out": "17:14:28"
},
{
"absence_date": "2021-02-08",
"time_in": "07:53:56",
"time_out": "17:09:15"
},
{
"absence_date": "2021-02-05",
"time_in": "07:53:32",
"time_out": "17:17:31"
}
],
"last_page": 4
}
}
Attendance.dart -> Model
#JsonSerializable()
class Attendance {
#JsonKey()
List<dynamic> data;
#JsonKey()
int last_page;
Attendance();
factory Attendance.fromJson(Map<String, dynamic> json) => _$AttendanceFromJson(json);
Map<String, dynamic> toJson() => _$AttendanceToJson(this);
}
ListView.dart -> _fecthJobs
Widget build(BuildContext context) {
return FutureBuilder<List<Job>>(
future: _fetchJobs(),
builder: (context, snapshot) {
print(snapshot.data);
if (snapshot.hasData) {
List<Job> data = snapshot.data;
return _jobsListView(data);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
);
}
Future<List<Job>> _fetchJobs() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var email = prefs.getString('email');
await api.attendances(email).then((items) async {
if (items.success == true) {
Attendance att = Attendance.fromJson(items.data);
print(att.data);
return att.data.map((job) => new Job.fromJson(job)).toList();
}
}).catchError((e) {
print('Exception $e');
});
}
I print att.data, it has the data API, but when it in snapshot.data it say it's null

_TypeError in call api flutter

Good afternoon, I am making a call to my api to bring the businesses that I have registered.
This is my model
class Shops{
Shops({
this.id,
this.name,
this.phone,
this.merchantType,
this.address,
this.city,
this.distance,
this.logo,
});
String id;
String name;
String phone;
String merchantType;
String address;
String city;
double distance;
String logo;
factory Shops.fromJson(Map<String, dynamic> json){
return Shops(
id: json["_id"],
name : json["name"],
phone : json["phone"],
merchantType : json["merchantType"],
address : json["address"],
city : json["city"],
distance : json["distance"].toDouble(),
logo : json["logo"],
);
}
}
Here I make the call
Future<Shops> getShops(var userLatitude, var userLongitude) async {
final response =
await http.get('https://dry-plateau-30024.herokuapp.com/v1/front/merchants?lat=$userLatitude&lng=$userLongitude');
if (response.statusCode == 200) {
return Shops.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load Shops');
}
}
so I show the results
FutureBuilder<Shops>(
future:
getShops(services.userLatitude, services.userLongitude),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.name);
} else if (snapshot.hasError) {
return Information(
title: 'No results found',
subtitle: 'It seems there is nothing in your area',
img: 'assets/nada.png',
);
} else {
return CircularProgressIndicator();
}
},
)
This returns me the following error
_TypeError (type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
I am evolving with the framework and the dart language, I am presented with these errors that perhaps for you are a newbie. I would appreciate a little help
Using the new link for the JSON you have given. Since it is a list we will have to cast it to a list and map through it. Before you were just returning one instance of ShopsFuture<Shops> instead of Future<List<Shops>>
class _CompaniesState extends State<Companies> {
Future<List<Shops>> getShops(var userLatitude, var userLongitude) async {
final response =
await http.get("https://dry-plateau-30024.herokuapp.com/v1/front/merchants?lat=-27.4885846&lng=-58.9509858");
if (response.statusCode == 200) {
// typecasting it into a list
var jsonData = json.decode(response.body) as List;
// Map through it and return it
return jsonData.map((shop) => Shops.fromJson(shop)).toList();
} else {
throw Exception('Failed to load Shops');
}
}
#override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder<List<Shops>>(
future: getShops(12, 20),
builder: (context, snapshot) {
if (snapshot.hasData) {
// Accessing the first map from the list and getting the name key
return Text(snapshot.data[0].name);
} else if (snapshot.hasError) {
return null;
return Information(
title: 'No results found',
subtitle: 'It seems there is nothing in your area',
img: 'assets/nada.png',
);
} else {
return CircularProgressIndicator();
}
},
));
}
}

Flutter FutureBuilder returning null data

I'm new to Flutter and Dart, and I'm trying to write a application to test it.
I have an api that I'm getting the data for the app, and was trying to use the StatefulWidget and the FutureBuilder.
When I run the method to call the api I have the results (used print() to test it), but when I get the data from loadData method it retrives null.
So loadData prints the data, initState and FutureBuilder the data returns null. What am I missing here.
I have added the service and the models used for the request... hope it help.
Future<CoachesModelRes> loadData(Profile _profile) async {
await getPost(_profile.getToken()).then((response) {
if (response.statusCode == 200) {
CoachesModelRes coaches = coachesModel.postFromJson(response.body);
if (coaches.count > 0) {
print(coaches.count);
print(coaches.coaches[0].description);
return coaches;
} else {
return null;
}
} else {
String code = response.statusCode.toString();
return null;
}
}).catchError((error) {
print(error.toString());
return null;
});
}
#override
void initState() {
super.initState();
print(widget.profile.getToken());
data = loadData(widget.profile);
data.then((data_) async {
var cenas = data_.count;
print("asdasd $cenas");
});
}
Future<CoachesModelRes> data;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: appWhiteColor,
appBar: applicationBar(),
drawer: adminDrawer(widget.profile, AdminDrawerListEnum.coaches, context),
body: FutureBuilder<CoachesModelRes>(
future: data,
builder: (context, snapshot) {
//print(snapshot.data.count.toString());
if (snapshot.hasData) {
return Text("nop");
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return Text("nop");
// By default, show a loading spinner.
return CircularProgressIndicator();
},
),
);
}
Future<http.Response> getPost(String token) async {
final response = await http.get(new Uri.http("$apiUrl", "$coachesEndPoint"),
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
HttpHeaders.authorizationHeader : 'Bearer $token'
},
);
return response;
}
CoachesModelRes postFromJson(String str) => CoachesModelRes.fromJson(json.decode(str));
class CoachesModelRes {
int count;
List<CoachModelRes> coaches;
CoachesModelRes({
this.count,
this.coaches,
});
factory CoachesModelRes.fromJson(Map<String, dynamic> json) => new CoachesModelRes(
count: json["count"],
coaches: (json["coaches"] as List).map((i) => CoachModelRes.fromJson(i)).toList(),
);
}
CoachModelRes postFromJson(String str) => CoachModelRes.fromJson(json.decode(str));
class CoachModelRes {
String id;
String firstName;
String lastName;
String description;
String username;
String notes;
List<String> roles;
CoachModelRes({
this.id,
this.firstName,
this.lastName,
this.description,
this.username,
this.notes,
this.roles,
});
factory CoachModelRes.fromJson(Map<String, dynamic> json) => new CoachModelRes(
id: json["id"],
firstName: json["firstName"],
lastName: json["lastName"],
description: json["description"],
username: json["username"],
notes: json["notes"],
roles: new List<String>.from(json["roles"]),
);
}
Future<CoachesModelRes> loadData(Profile _profile) async {
final response = await getPost(_profile.getToken());
try{if (response.statusCode == 200) {
CoachesModelRes coaches = coachesModel.postFromJson(response.body);
if (coaches.count > 0) {
print(coaches.count);
print(coaches.coaches[0].description);
return coaches;
} else {
return null;
}
} else {
String code = response.statusCode.toString();
return null;
}}catch(e){
return null ;
}
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: appWhiteColor,
appBar: applicationBar(),
drawer: adminDrawer(widget.profile, AdminDrawerListEnum.coaches, context),
body: FutureBuilder<CoachesModelRes>(
future: loadData(widget.profile),
builder: (context, snapshot) {
//print(snapshot.data.count.toString());
if (snapshot.hasData) {
return Text("nop");
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return Text("nop");
// By default, show a loading spinner.
return CircularProgressIndicator();
},
),
);
}
The issue here is that the return statement should be at the end of the method.
Because the getPost will return data to the loadData.
And when the getPost finishes the loadData will return data to the method that invoked him.
In my case, the loadData is not returning anything so the snapshot in the FutureBuilder it's always null.
It's logic that it is this way now, but at the time I could not figure it out :\
Future<CoachesModelRes> loadData(Profile _profile) async {
// So I need to create a variable to return
CoachesModelRes response;
//-----
await getPost(_profile.getToken()).then((response) {
if (response.statusCode == 200) {
CoachesModelRes coaches = coachesModel.postFromJson(response.body);
if (coaches.count > 0) {
print(coaches.count);
print(coaches.coaches[0].description);
// Set the variable value
response = coaches;
//-----
} else {
// Set the variable value
response = null;
//-----
}
} else {
String code = response.statusCode.toString();
// Set the variable value
response = null;
//-----
}
}).catchError((error) {
print(error.toString());
// Set the variable value
response = null;
//-----
});
// And at the end return the response variable
return response;
//-----
}