I'm trying to make unit test for my app but I get some issues with the expect() function.
This is my test:
test('User should register.', () async {
final _response = await _api.register(mockSuccessfullRegisterUser);
mockSuccessfullLoginUser = User(email: mockSuccessfullRegisterUser.email, password: mockSuccessfullRegisterUser.password);
print(mockSuccessfullLoginUser.email);
expect(_response.runtimeType, SuccessWithTokenResponseState);
});
My _response can return multiple types of responses like: SuccessWithTokenState, ErrorState, …
The expect function gives me this error:
TestFailure (Expected: Type:<SuccessWithTokenResponseState<dynamic>>
Actual: Type:<SuccessWithTokenResponseState<NetworkResponse>>
)
Shouldn't SuccessWithTokenResponseState be equal to SuccessWithTokenResponseState?
When you use a generic type without additional type it's fallback to Type<dynamic> try to use the correct type that you expect
expect(_response.runtimeType, SuccessWithTokenResponseState<NetworkResponse>);
I found the answer!
expect(_response.runtimeType is SuccessWithTokenResponseState, true);
Related
I am trying to write unit tests for a flutter app and I can't get this one test case to work correctly.
Here is the function returning Future<Either<WeatherData, DataError>>:
#override
Future<Either<WeatherData, DataError>> fetchWeatherByCity({required String city}) async {
try {
var response = await apiService.fetchWeatherByCity(city: city);
if (response.statusCode == 200) {
return Left(WeatherData.fromJson(jsonDecode(response.body)));
} else {
return Right(DataError(title: "Error", description: "Desc", code: 0, url: "NoUrl"));
}
} catch (error) {
AppException exception = error as AppException;
return Right(DataError(
title: exception.title, description: exception.description, code: exception.code, url: exception.url));
}
}
Here is the code where I am trying to write the unit test:
sut = WeatherRepositoryImpl(apiService: mockWeatherApiService);
test(
"get weather by city DataError 1 - Error 404 ",
() async {
when(mockWeatherApiService.fetchWeatherByCity(city: "city"))
.thenAnswer((_) async => Future.value(weatherRepoMockData.badResponse));
final result = await sut.fetchWeatherByCity(city: "city");
verify(mockWeatherApiService.fetchWeatherByCity(city: "city")).called(1);
expect(result, isInstanceOf<DataError>);
verifyNoMoreInteractions(mockWeatherApiService);
},
);
When I run this specific test, I receive this error:
Expected: <Instance of 'DataError'>
Actual: Right<WeatherData, DataError>:<Right(Instance of 'DataError')>
Which: is not an instance of 'DataError'
What I am not getting here? What should I be expecting from the function for the test to pass successfully?
You are directly using the result which is actually a wrapper and has a type of Either<WeatherData, DataError>.
You need to unwrap the value using the fold method on the result and then expect accordingly, So in your code you can do something like this to make it work:
final result = await sut.fetchWeatherByCity(city: "city");
result.fold(
(left) => fail('test failed'),
(right) {
expect(result, isInstanceOf<DataError>);
});
verifyNoMoreInteractions(mockWeatherApiService);
Hope this helps.
You need to either make the expected value a Right(), or extract the right side of the actual value. Doing either of those will match, but as it is, you're comparing a wrapped value with an unwrapped value.
I tried to decode JSON Data using JsonDecode(). when I try to access each member through [] indexing and try to print them, the above error is printed onto my terminal. I am trying to build an expense tracker app that uses a pie chart to display the different expenses of the user.
Here is a small snippet of the code. I can provide more if needed.
var expense = Expense(
_dateController.text, categories.toString(), money);
token.storage.read(key: "jwt").then((value) {
AuthService().getExpense(value).then((val) => {
print(val), // this prints the json data
mv = jsonDecode(val), // i tried to decode it
item = mv[0], //acessing each member
print(item['category']),
});
});
Once again the error I get is:
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: type 'Response' is not a subtype of type 'String'
it is giviing error because return type of api call is of type Response and print function can print string only try to conver that value into string using .toString method. also if you are making an api call you should accces its body to print.
for example :
token.storage.read(key: "jwt").then((value) {
AuthService().getExpense(value).then((val) => {
print(val.body.toString), // change here
});
});
I am trying to use mockito to mock a http client and return some values based on the Uri. I have the following code but got type 'Null' is not a subtype of type 'Future<Response>' error.
Future<MockHttpClientBuilder> withListPostEndpoint() async {
Uri uri = Uri(
scheme: 'https',
host: this._host,
path: '/Posts',
query: 'sortBy=CreatedAt&sortOrder=Descending&pageSize=15&pageOffset=0');
//Uri uri = Uri.parse('https://localhost/Posts?sortBy=CreatedAt&sortOrder=Descending&pageSize=15&pageOffset=0');
String content = await File('test/shared/mock_http_client_payloads/list_post_response.json').readAsString();
Map<String, String> headers = new Map();
headers[HttpHeaders.contentTypeHeader] = 'application/json';
when(_client.get(uri, headers: headers)).thenAnswer((_) async => Response(content, 200));
return this;
}
I tried to use two different ways to generate Uri object (one is them is commented). From the error message, the error happens at line when(_client.get(uri, headers: headers)).thenAnswer((_) async => Response(content, 200));.
In addition, the error happens before the mocked endpoint is actually called. Seems like the error happens when the mock endpoint is setup. I put the breakpoint at the production code where the endpoint is called but the breakpoint is not reaches.
Can anyone please help to have a look? Thank you
I forgot to run dart run build_runner build to generate the mock file. After running the command, the error is resolved.
Help is much appreciated how to trace down this issue, because I am running out of ideas.
I am calling the function getOrderCollection, below, but it aborts after the first line var myCompanyDoc = await FirebaseFirestore.instance.collection('companies').doc(myCompany).get(); Without trowing anything to the console or jumping into some library when debugging. When I click next statement it jumps back to the calling function.
I am authenticated to the database, companyCollection = FirebaseFirestore.instance.collection('companies') provides an initialized object pointing to the collection and myCompany is a constant with the document id entered by copy/paste.
If some rules for the database but I can't see successful or denied queries with the monitor.
Any ideas how I can proceed tracing down the issue?
Future<void> getOrderCollection() async {
var myCompanyDoc = await FirebaseFirestore.instance.collection('companies').doc(myCompany).get();
print("companyDoc fetched");
final myDeliveryDocRef = myCompanyDoc.data()['delivery'].toString();
orderCollection = FirebaseFirestore.instance.collection('companies').doc(myCompany).collection('features').doc(myDeliveryDocRef).collection('orders');
orderBriefDoc = FirebaseFirestore.instance.collection('companies').doc(myCompany).collection('features').doc(myDeliveryDocRef);
}
UPDATE: This is collection > document what corresponds to final String myCompany = '4U4kZKXkr3rHA6B04S5K';
As we discussed in your comments, the issue was that you forgot to await the getOrderCollection() function. Even though, as you mentioned, your caller function _deliveryRepository.initRepository() was awaited, you still had to await getOrderCollection() inside your caller method to make sure that the code is waiting for the getOrderCollection() to be executed before it proceeds to the next line.
In general, you want to have some error handling and to type the known types/classes (avoid using var).
Error handling - for async/await place the code inside a try/catch.
Typing - Dart is type safe, which is really great to prevent runtime errors.
Depending on your setup, you might be able to hover over the Firestore.instance.collection(...).doc(...) to see the return type. .doc(...).get() returns a DocumentSnapshot and .collection(...).get() returns a CollectionSnapshot.
Using the above, it should be easier to debug:
Future<void> getOrderCollection() async {
try {
DocumentSnapshot myCompanyDoc = await FirebaseFirestore.instance.collection('companies').doc(myCompany).get();
print("companyDoc fetched");
final myDeliveryDocRef = myCompanyDoc.data()['delivery'].toString();
} catch(e) {
print('Error: ' + e.toString());
}
}
Don't forget to await your other 2 Firestore queries.
I am trying to write a simple test in flutter using MockClient, but I can't seem to get it to work.
Here is the code I am trying to test:
getItemById(int id) async {
final response = await client.get("$_host/item/$id.json");
final decodedJson = json.decode(response.body);
return Item.fromJson(decodedJson);
}
Here is the test code:
test("Test getting item by id", () async {
final newsApi = NewsAPI();
newsApi.client = MockClient((request) async {
final jsonMap = {'id': 123};
Response(json.encode(jsonMap), 200);
});
final item = await newsApi.getItemById(123);
print("Items: ${item.toString()}"); //<-- dosen't print anything.
expect(item.id , 123);
});
When I run the test, it fails with the following message:
NoSuchMethodError: The getter 'bodyBytes' was called on null.
Receiver: null
Tried calling: bodyBytes
I am guessing the issue here is that nothing is returned from the MockClient when I make the call to the getItemById method, but I am not sure why.
I had the same exact issue. You have to return the Response
return Response(json.encode(jsonMap), 200);
Mock expects test function to be EXACTLY as you real function (including OPTIONAL parameters and so on). If both does not match it returns NULL and that is what is happening with your code. Double check to see where your test function is different of original function.