Closed irangareddy closed 7 months ago
With the error:
type '
Null
' is not a subtype of type 'Future<HttpResponse<OnSuccess>>
'
and the signature of the method being stubbed:
Future<HttpResponse<OnSuccess>> registerPhoneNumber(Mobile mobile);
My guess is that the generated Mockito code is not creating a proper stub for registerPhoneNumber
.
Can you clarify one thing? Where does HttpResponse
come from? My guess is dart:io
, but that is not shown as an import in the "AuthService" file. Is there a missing import? A missing import could result in the error you show.
If the missing import was just in pasting into GitHub, can you show the contents of the generated mock? It's probably a huge file, so I think just the imports and the registerPhoneNumber
override body should be sufficient.
HttpResponse
comes from import 'package:dio/dio.dart';
// Mocks generated by Mockito 5.4.2 from annotations
// in feebac/test/auth_service_test.dart.
// Do not manually edit this file.
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i5;
import 'package:feebac/data/data_sources.dart' as _i6;
import 'package:feebac/utils/utils.dart' as _i3;
import 'package:mockito/mockito.dart' as _i1;
import 'package:retrofit/retrofit.dart' as _i2;
import 'auth_service_test.dart' as _i4;
// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
// ignore_for_file: avoid_setters_without_getters
// ignore_for_file: comment_references
// ignore_for_file: implementation_imports
// ignore_for_file: invalid_use_of_visible_for_testing_member
// ignore_for_file: prefer_const_constructors
// ignore_for_file: unnecessary_parenthesis
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class
class _FakeHttpResponse_0<T> extends _i1.SmartFake
implements _i2.HttpResponse<T> {
_FakeHttpResponse_0(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeDataState_1<T> extends _i1.SmartFake implements _i3.DataState<T> {
_FakeDataState_1(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
/// A class which mocks [MockAuthService].
///
/// See the documentation for Mockito's code generation for more information.
class MockMockAuthService extends _i1.Mock implements _i4.MockAuthService {
MockMockAuthService() {
_i1.throwOnMissingStub(this);
}
@override
_i5.Future<_i2.HttpResponse<_i6.OnSuccess>> registerPhoneNumber(
_i6.Mobile? mobile) =>
(super.noSuchMethod(
Invocation.method(
#registerPhoneNumber,
[mobile],
),
returnValue: _i5.Future<_i2.HttpResponse<_i6.OnSuccess>>.value(
_FakeHttpResponse_0<_i6.OnSuccess>(
this,
Invocation.method(
#registerPhoneNumber,
[mobile],
),
)),
) as _i5.Future<_i2.HttpResponse<_i6.OnSuccess>>);
@override
_i5.Future<_i2.HttpResponse<_i6.OnSuccess>> verifyOTP(
Map<String, dynamic>? requestBody) =>
(super.noSuchMethod(
Invocation.method(
#verifyOTP,
[requestBody],
),
returnValue: _i5.Future<_i2.HttpResponse<_i6.OnSuccess>>.value(
_FakeHttpResponse_0<_i6.OnSuccess>(
this,
Invocation.method(
#verifyOTP,
[requestBody],
),
)),
) as _i5.Future<_i2.HttpResponse<_i6.OnSuccess>>);
}
/// A class which mocks [MockAuthRepository].
///
/// See the documentation for Mockito's code generation for more information.
class MockMockAuthRepository extends _i1.Mock
implements _i4.MockAuthRepository {
MockMockAuthRepository() {
_i1.throwOnMissingStub(this);
}
@override
_i5.Future<_i3.DataState<_i6.OnSuccess>> phoneLogin(String? mobileNumber) =>
(super.noSuchMethod(
Invocation.method(
#phoneLogin,
[mobileNumber],
),
returnValue: _i5.Future<_i3.DataState<_i6.OnSuccess>>.value(
_FakeDataState_1<_i6.OnSuccess>(
this,
Invocation.method(
#phoneLogin,
[mobileNumber],
),
)),
) as _i5.Future<_i3.DataState<_i6.OnSuccess>>);
}
Oh whoa I totally missed this:
class MockAuthService extends Mock implements AuthService {}
class MockAuthRepository extends Mock implements AuthRepository {}
@GenerateMocks([MockAuthService, MockAuthRepository])
The mocks should either be manually created or generated, not both. I would remove the two class delcarations here, and generate the mocks with
@GenerateNiceMocks([AuthService, AuthRepository])
We should maybe add a check that classes which already inherit from Mock cannot be used to generate mocks.
Thanks @srawlins, Kind of my code has started working, but I have an exception even on a valid phone number too. Am I missing here exactly
Exception has occurred.
MissingStubError (MissingStubError: 'phoneLogin'
No stub was found which matches the arguments of this method call:
phoneLogin('xxxxxxxx')
Add a stub for this method using Mockito's 'when' API, or generate the MockAuthRepository mock with the @GenerateNiceMocks annotation (see https://pub.dev/documentation/mockito/latest/annotations/MockSpec-class.html).)
@GenerateMocks([AuthService, AuthRepository])
void main() {
late MockAuthService mockAuthService;
late MockAuthRepository mockAuthRepository;
setUpAll(() {
mockAuthService = MockAuthService();
mockAuthRepository = MockAuthRepository();
});
group('Auth Validation Tests', () {
const validMobileNumber = 'xxxxxxxx';
final response = HttpResponse(
OnSuccess(
isSuccess: true,
message: 'Successfully OTP sent to the user.',
),
Response(requestOptions: RequestOptions()),
);
test('sucessfully OTP Sent', () async {
// Arrange
when(
mockAuthService.registerPhoneNumber(Mobile(mobile: validMobileNumber)),
).thenAnswer((_) async => response);
// Act
final result = await mockAuthRepository.phoneLogin(validMobileNumber);
// Assert
expect(result.data, isA<OnSuccess>());
verify(
mockAuthService.registerPhoneNumber(Mobile(mobile: validMobileNumber)),
);
});
});
}
I'm glad we got past your code generation issue. At this point, I can't offer any further support. User forums like StackOverflow are a better place to ask questions like this.
Exception has occurred. MissingStubError (MissingStubError: 'phoneLogin' No stub was found which matches the arguments of this method call: phoneLogin('xxxxxxxx')
Add a stub for this method using Mockito's 'when' API, or generate the MockAuthRepository mock with the @GenerateNiceMocks annotation (see https://pub.dev/documentation/mockito/latest/annotations/MockSpec-class.html).)
final result = await mockAuthRepository.phoneLogin(validMobileNumber);
I can only repeat the error message to explain what went wrong: No stub was found for phoneLogin
. The method was called, but no stub was set up.
I can't thank you enough for this great help. If possible, I will write a good article around this. Thank you so much.
Regarding how to write valid tests with Mockito to test the retrofit service, I have perused an ample amount of online resources and read a few blogs, but to no avail. I attempted to write tests for both the service and repository, but encountered the same error each time. I have exhausted all available options, including closed and open, in an attempt to rectify the issue. Please provide assistance in writing this test effectively.
Version
Issue while running tests
AuthServiceTest
Models
OnSuccess
Mobile
Generics
DataState
Backend
AuthService
AuthRepository