import 'package:shared_preferences/shared_preferences.dart';
class LoginViewModel {
final SharedPreferences sharedPreferences;
LoginViewModel({
required this.sharedPreferences,
});
final Map<String, String?> _cache = {};
bool login(String email, String password) {
if (_cache.containsKey(email)) {
return password == _cache[email];
}
final storedPassword = sharedPreferences.getString(email);
_cache[email] = storedPassword;
return password == storedPassword;
}
}
final Map<String, String?> _cache = {};
// Expose this method for testing purposes to set values in _cache
@visibleForTesting
void putToCache(String email, String? password) {
_cache[email] = password;
}
group('login', () {
test('login should return true when the cache contains the password input even when the password is incorrect', () {
// Arrange
final mockSharedPreferences = MockSharedPreferences();
final loginViewModel = LoginViewModel(
sharedPreferences: mockSharedPreferences,
);
String email = 'ntminh@gmail.com';
String password = 'abc';
loginViewModel.putToCache(email, 'abc'); // NEW
// Stubbing
when(() => mockSharedPreferences.getString(email))
.thenReturn('123456');
// Act
final result = loginViewModel.login(email, password);
// Assert
expect(result, true);
});
test('login should return false when the cache does not contain the password input and the password is incorrect', () {
// Arrange
final mockSharedPreferences = MockSharedPreferences();
final loginViewModel = LoginViewModel(
sharedPreferences: mockSharedPreferences,
);
String email = 'ntminh@gmail.com';
String password = 'abc';
// Stubbing
when(() => mockSharedPreferences.getString(email))
.thenReturn('123456');
// Act
final result = loginViewModel.login(email, password);
// Assert
expect(result, false);
});
});
void main() {
late MockSharedPreferences mockSharedPreferences;
late LoginViewModel loginViewModel;
setUp(() {
mockSharedPreferences = MockSharedPreferences();
loginViewModel = LoginViewModel(
sharedPreferences: mockSharedPreferences,
);
});
...
}
setUp (initialization) -> test case 1 -> setUp (re-initialization) -> test case 2
setUpAll(() async {
await Isar.initializeIsarCore(download: true);
isar = await Isar.open([JobSchema], directory: '');
});
tearDownAll(() async {
await isar.close();
});
import 'package:isar/isar.dart';
part 'job_data.g.dart';
@collection
class JobData {
Id id = Isar.autoIncrement;
late String title;
}
class HomeBloc {
HomeBloc({required this.isar}) {
_streamSubscription = isar.jobDatas
.where()
.watch(fireImmediately: true)
.listen((event) {
_streamController.add(event);
});
}
final Isar isar;
final _streamController =
StreamController<List<JobData>>.broadcast();
StreamSubscription? _streamSubscription;
Stream<List<JobData>> get data => _streamController.stream;
void close() {
_streamSubscription?.cancel();
_streamController.close();
_streamSubscription = null;
}
}
void main() {
late Isar isar;
late HomeBloc homeBloc;
setUp(() async {
await isar.writeTxn(() async => isar.clear());
homeBloc = HomeBloc(isar: isar);
});
tearDown(() {
homeBloc.close();
});
setUpAll(() async {
await Isar.initializeIsarCore(download: true);
isar = await Isar.open(
[JobDataSchema],
directory: '',
);
});
tearDownAll(() {
isar.close();
});
}
test('data should emit what Isar.watchData emits', () async {
expectLater(
homeBloc.data,
emitsInOrder([
[],
[JobData()..title = 'IT'],
[JobData()..title = 'IT', JobData()..title = 'Teacher'],
]));
// put data to Isar
await isar.writeTxn(() async {
isar.jobDatas.put(JobData()..title = 'IT');
});
await isar.writeTxn(() async {
isar.jobDatas.put(JobData()..title = 'Teacher');
});
});
tearDown(() {
resetMocktailState();
});