Examples
Testing Setup Example
A ready-to-copy test suite harness for Authyra-based auth, fake provider, InMemoryStorage, no network.
A complete test/auth_test.dart you can adapt directly. No network, no singleton, no mocking framework.
test/auth_test.dart
import 'package:test/test.dart';
import 'package:authyra/authyra.dart';
const _validEmail = 'alice@example.com';
const _validPassword = 'secret';
AuthyraClient _makeClient({AuthCallbacks? callbacks}) => AuthyraClient(
providers: [
CredentialsProvider.withTokens(
id: 'email',
authorize: (creds) async {
if (creds?.email == _validEmail && creds?.password == _validPassword) {
return AuthSignInResult(
user: AuthUser(id: '1', email: _validEmail),
accessToken: 'fake-access',
refreshToken: 'fake-refresh',
expiresAt: DateTime.now().add(const Duration(hours: 1)),
);
}
return null;
},
),
],
storage: InMemoryStorage(),
callbacks: callbacks,
);
void main() {
group('sign in / sign out', () {
late AuthyraClient client;
setUp(() async {
client = _makeClient();
await client.initialize();
});
test('returns user on valid credentials', () async {
final user = await client.signIn('email', params: CredentialsSignInParams(
email: _validEmail,
password: _validPassword,
));
expect(user.email, _validEmail);
});
test('stores an access token in the session', () async {
await client.signIn('email', params: CredentialsSignInParams(
email: _validEmail, password: _validPassword,
));
expect(await client.getAccessToken(), 'fake-access');
});
test('throws on wrong password', () {
expect(
() => client.signIn('email', params: CredentialsSignInParams(
email: _validEmail, password: 'wrong',
)),
throwsA(isA<AuthenticationFailedException>()),
);
});
test('isAuthenticated is false after sign out', () async {
await client.signIn('email', params: CredentialsSignInParams(
email: _validEmail, password: _validPassword,
));
await client.signOut();
expect(await client.isAuthenticated(), isFalse);
});
});
group('events', () {
test('emits SignInEvent on success', () async {
final client = _makeClient();
await client.initialize();
SignInEvent? captured;
client.events.on<SignInEvent>((e) => captured = e);
await client.signIn('email', params: CredentialsSignInParams(
email: _validEmail, password: _validPassword,
));
expect(captured, isNotNull);
expect(captured!.user.email, _validEmail);
});
});
group('callbacks', () {
test('a denial blocks sign-in and persists nothing', () async {
final client = _makeClient(callbacks: _DenyAllCallbacks());
await client.initialize();
expect(
() => client.signIn('email', params: CredentialsSignInParams(
email: _validEmail, password: _validPassword,
)),
throwsA(isA<AuthenticationFailedException>()),
);
expect(await client.isAuthenticated(), isFalse);
});
});
}
class _DenyAllCallbacks extends AuthCallbacks {
@override
Future<CallbackResult> onBeforeSignIn(String providerName, AuthSignInParams? params) async {
return const CallbackResult.deny('blocked for test');
}
}
Isolation
Give each test its own InMemoryStorage(), it's a plain in-memory map with no cross-test cleanup, so reusing one instance leaks state between tests.
If you use Authyra.instance in the code under test
tearDown(() async {
if (Authyra.isInitialized) {
await Authyra.instance.dispose();
}
});
Prefer testing against an injected AuthyraClient wherever your app's structure allows it; it sidesteps the singleton entirely.