BehaviorSubject stream unit test, fail actual data - flutter

can You please help me to understand how to test the BehaviorSubject with my custom class(TestClass).
the test returns Instance of 'BehaviorSubject<TestClass>' instead of Instance of 'TestClass.
but with primitive types it work fine
Full error:
ERROR: Expected: should emit an event that <Instance of 'TestClass'>
Actual: <Instance of 'BehaviorSubject<TestClass>'>
Which: emitted • Instance of 'TestClass'
bloc example:
class TestDataBloc {
final testSubject = BehaviorSubject<TestClass>();
Observable<TestClass> get paymentStream => testSubject.stream;
createOrder() {
final TestClass _testData = TestClass(
id: 100,
data: "xxx",
);
testSubject.sink.add(_testData);
}
dispose() async {
await testSubject.drain();
testSubject.close();
}
}
test:
test('_testData', () async {
TestDataBloc _testDataBloc = TestDataBloc();
final TestClass _testData = TestClass(
id: 100,
data: "xxx",
);
expect(
_testDataBloc.testSubject.stream,
emitsInOrder(
<TestClass>[
_testData,
],
),
);
_testDataBloc.createOrder();
});
Thanks

Make sure you have an equality operator defined for TestClass

Related

Flutter Unit Testing with Mockito multiple stubs

I'm quite new to unit testing and I want to test a method of a service that calls conditionally a second method. The problem I'm facing now is that I'm getting a missing MissingStubError even I have created the missing stub.
mockito: 5.3.2
Error Message:
MissingStubError: 'createCashbookItem'
No stub was found which matches the arguments of this method call:
createCashbookItem(Instance of 'CashbookItem')
Test:
#GenerateMocks([CashbookRepository, ReceiptRepository, CashbookItemRepository])
void main() {
late BookingService bookingService;
late MockCashbookRepository mockCashbookRepository;
late MockCashbookItemRepository mockCashbookItemRepository;
late MockReceiptRepository mockReceiptRepository;
setUp(() {
mockCashbookRepository = MockCashbookRepository();
mockCashbookItemRepository = MockCashbookItemRepository();
mockReceiptRepository = MockReceiptRepository();
bookingService = BookingServiceImpl(
receiptRepository: mockReceiptRepository,
cashbookItemRepository: mockCashbookItemRepository,
cashbookRepository: mockCashbookRepository,
);
});
group("bookings", () {
var t_OldReceipt = Receipt.empty();
var t_NewReceipt = Receipt.empty();
test("create booking", () async {
t_OldReceipt = t_OldReceipt.copyWith(
amount: 10,
totalAmount: 10,
taking: true,
category: "test",
taxRate: 0,
paymentType: kPaymentTypeBar,
documentNumber: "1",
taxAmount: 0,
receiptDate: DateTime.now(),
year: "2023",
yearMonth: "20232",
yearMonthDay: "2023210",
contact: Contact.empty());
// arrange
var cashbookItem = CashbookItem.fromReceipt(t_OldReceipt);
when(mockReceiptRepository.createReceipt(t_OldReceipt)).thenAnswer((realInvocation) async => const Right(unit));
when(mockCashbookItemRepository.createCashbookItem(cashbookItem)).thenAnswer((realInvocation) async => const Right(unit));
// act
final result = await bookingService.createBooking(t_OldReceipt);
// assert
expect(result, const Right(unit));
});
});
}
Method that I want to test:
Future<Either<ReceiptFailure, Unit>> createBooking(Receipt receipt) async {
Either<ReceiptFailure, Unit>? receiptFailureOrSuccess;
Either<cashbook_failures.CashbookFailure, Unit>? cashbookFailureOrSuccess;
receiptFailureOrSuccess = await receiptRepository.createReceipt(receipt);
if (receiptFailureOrSuccess.isLeft()) {
return receiptFailureOrSuccess;
}
if (receipt.paymentType == kPaymentTypeBar) {
cashbookFailureOrSuccess = await cashbookItemRepository.createCashbookItem(CashbookItem.fromReceipt(receipt));
if(cashbookFailureOrSuccess.isLeft()){
receiptRepository.deleteReceipt(receipt.id.value);
return left(CreateCashbookItemFromReceiptFailure());
} else {
return right(unit);
}
}
return receiptFailureOrSuccess;
}
I have added a stub for the error and my assumption was that it is possible to have two stubs in one test. I want to test if the method createCashbookItem inside createBooking is called.

Getting type 'Null' is not a subtype of type 'Future<Response>' in Flutter

I'm trying to run a text in flutter using mockito but I have been getting a error of
type 'Null' is not a subtype of type 'Future<Response>'
Below is the code
class MockClient extends Mock implements http.Client {}
void main() {
var client = MockClient();
var sut = AuthApi('http:baseUrl', client);
setUp(() {
client;
sut;
});
group('signin', () {
var credential = Credential(
type: AuthType.email,
email: 'email#email',
password: 'pass',
);
test('should return error when status is not 200', () async {
when(client.post(Uri(), body: anyNamed('body')))
.thenAnswer((_) async => http.Response('{}', 404));
var result = await sut.signIn(credential);
expect(result, isA<ErrorResult>());
});
});
}
I have tried to pass
when(client.post(any, body: anyNamed('body')))
but I got any error of: The argument type 'Null' can't be assigned to the parameter type 'Uri'
Since Mockito migrated to a null safety code, you need to Override the method with a new declaration inside the mock class. At a body of the override method call super.noSuchMethod, passing in an Invocation object which includes all of the values passed to the override, and pass a second argument to super.noSuchMethod, a value which can function as a return value.
Here is an example:
class MockClient extends Mock implements http.Client {
#override
Future<http.Response> post(Uri uri, {String body}) => super.noSuchMethod(Invocation.method(#post, [uri, body]), returnValue: http.Response('{}', 404));
}
Please note that your method parameters may be different

flutter unit testing stubbed method returns null

I,m unit testing flutter class using mockito. I stubbed one method using 'when()' but it returns null. is there something wrong in my testing?. I have used freezed union to generate Result class. My Repository is an abstract class
this is my test class
class MockRepository extends Mock implements Repository {}
void main() {
late CryptoUseCases useCases;
late MockRepository repository;
final Result<List<Crypto>, Exception> data = const Result.success([
Crypto(
id: 1,
name: 'Bitcoin',
symbol: 'BTC',
priceUsd: 4000,
availableSupply: 879787908,
logo: '',
volumeUsd24h: 786876,
totalSupply: 876587,
marketCapUsd: 698,
maxSupply: 867987,
rank: 1,
),
Crypto(
id: 3,
name: 'Euthereum',
symbol: 'ETH',
priceUsd: 134,
availableSupply: 879787908,
logo: '',
volumeUsd24h: 786876,
totalSupply: 876587,
marketCapUsd: 698,
maxSupply: 867987,
rank: 2,
),
]);
setUp(() {
repository = MockRepository();
useCases = CryptoUseCases(repository);
});
test('getCryptos return a list of crypto', () async {
//arrange
when(repository.getCryptos()).thenAnswer((_) async => data);
//act
final result = await useCases.getCryptos();
//assert
expect(result, equals(data));
verify(repository.getCryptos()).called(1);
verifyNoMoreInteractions(repository);
});
}
this is my class
class CryptoUseCases {
final Repository repository;
CryptoUseCases(this.repository);
Future<Result<List<Crypto>, Exception>> getCryptos() async {
final result = await repository.getCryptos();
result.when(success: (data) {
return Result.success(data);
}, error: (e) {
return Result.error(e);
});
return Result.error(Exception());
}
}
i'm using freezed here. is that a problem?
this is the error
type 'Null' is not a subtype of type 'Future<Result<List<Crypto>, Exception>>'
package:crypto_app/src/domain/repositories/repository.dart 6:43 MockRepository.getCryptos
test\use_cases_test.dart 51:21 main.<fn>
test\use_cases_test.dart 49:46
found the answer after some tries.
I believe the null error is caused due to null safe dart feature.
So to create a mock for null safe dart, we need to anotate #GenerateMocks() above the main method of test.
In my case
#GenerateMocks([Repository])
void main(){}
and use buildrunner to generate code.
after this, this code worked fine

How to mock a future method and not get type 'Null' is not a subtype of type 'Future<>' in flutter

I want to mock this class and this specific method
class FeedApiService extends ApiService {
Future<FeedResponse> fetchFeed(Map<String, String> params) async {
...
}
...
}
My unit test is like this
class FeedApiServiceMock extends Mock implements FeedApiService {}
void main() {
test('..', () {
FeedApiServiceMock feedApiServiceMock = FeedApiServiceMock();
when(feedApiServiceMock.fetchFeed({})).thenAnswer(
(_) => Future.value(FeedResponse(items: 1)),
);
expect(await feedApiServiceMock.fetchFeed({}).items, 1);
});
}
I just want to see that fetch feed is mocked correctly, but I'm getting this error:
type 'Null' is not a subtype of type 'Future<FeedResponse>'
See if adding async in both the test and thenAnswer method solves the problem.
void main() {
test('..', () async{
FeedApiServiceMock feedApiServiceMock = FeedApiServiceMock();
when(feedApiServiceMock.fetchFeed({})).thenAnswer(
(_) async=> Future.value(FeedResponse(items: 1)),
);
expect(await feedApiServiceMock.fetchFeed({}).items, 1);
});
}

Flutter test GraphQL query

I want to test my GraphQL Query. I have my GraphQL client, and I use a remote datasource to do my requests.
class MockGraphQLClient extends Mock implements GraphQLClient {}
void main() {
RemoteDataSource RemoteDataSource;
MockGraphQLClient mockClient;
setUp(() {
mockClient = MockGraphQLClient();
RemoteDataSource = RemoteDataSource(client: mockClient);
});
group('RemoteDataSource', () {
group('getDetails', () {
test(
'should preform a query with get details with id variable',
() async {
final id = "id";
when(
mockClient.query(
QueryOptions(
documentNode: gql(Queries.getDetailsQuery),
variables: {
'id': id,
},
),
),
).thenAnswer((_) async => QueryResult(
data: json.decode(fixture('details.json'))['data'])));
await RemoteDataSource.getDetailsQuery(id);
verify(mockClient.query(
QueryOptions(
documentNode: gql(Queries.getDetailsQuery),
variables: {
'id': id,
},
),
));
});
});
});
}
I would like to know how to mock the response of my query. Currently it does not return a result, it returns null
But I don't understand why my query returns null, although I have mocked my client, and in my "when" method I use a "thenAnwser" to return the desired value
final GraphQLClient client;
ChatroomRemoteDataSource({this.client});
#override
Future<Model> getDetails(String id) async {
try {
final result = await client.query(QueryOptions(
documentNode: gql(Queries.getDetailsQuery),
variables: {
'id': id,
},
)); // return => null ????
if (result.data == null) {
return [];
}
return result.data['details']
} on Exception catch (exception) {
throw ServerException();
}
}
The argument on which when should mock an answer for is quite complex. You might be easier to just use any in your test case.
when(mockClient.query(any)).thenAnswer((_) async => QueryResult(
data: json.decode(fixture('details.json'))['data'])));
any is provided by Mockito to match any argument.
In the
graphql_flutter: ^5.0.0
you need the add source as null or QueryResultSource.network, when call method when can you pass any so you don't need to pass QueryOptions( documentNode: gql(Queries.getDetailsQuery), variables: { 'id': id, }, ),
here is final code:
when(mockClient.query(any)).thenAnswer((_) async => QueryResult( data: json.decode(fixture('details.json'))['data'], ,source: null)));
any is not accepted with graphQLClient.query(any)) as it accepts non nullable QueryOptions<dynamic>
Using mockito: ^5.1.0 , you will get the warning: The argument type 'Null' can't be assigned to the parameter type 'QueryOptions<dynamic>'
I solved it by creating the mocked QueryOptions as:
class SutQueryOption extends Mock implements QueryOptions {}
void main() {
SutQueryOption _mockedQueryOption;
....
setUp(() {
SutQueryOption _mockedQueryOption = MockedQueryOptions();
....
});
when(mockClient.query(_mockedQueryOption)).thenAnswer((_) async => ....