Introduction
This article demonstrates how to unit-test Shared Preferences in Flutter projects.
This article assumes that the reader is familiar with Flutter development and the Dart language.
The code in the demo was created using Flutter Channel stable, 2.5.3
.
Problem Statement
We have a SharedPreferencesUtil
class that makes use of the SharedPreferences
object to store and retrieve an integer count
. Our task is to unit-test the methods of this class.
The class is shown below:
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
class SharedPreferencesUtil {
SharedPreferencesUtil({required this.sharedPreferences});
final SharedPreferences sharedPreferences;
@visibleForTesting
static const String countKey = 'counter';
int getCount() {
return sharedPreferences.getInt(countKey) ?? 0;
}
Future<bool> setCount(int count) async {
return sharedPreferences.setInt(countKey, count);
}
}
Testing the methods
In the SharedPreferencesUtil
class above, the SharedPreferences
object is passed through the constructor and it is used in the following methods:
getCount()
: To return the value of the count integer stored inSharedPreferences
with thecountKey
key and return 0 if the value inSharedPreferences
isnull
setCount()
: To set the value of count int with thecountKey
key inSharedPreferences
In order to write a test, we need to mock the SharedPreferences
object that we pass into the SharedPreferencesUtil
class.
This is done using the SharedPreferences.setMockInitialValues() static method.
setMockInitialValues()
Initializes the shared preferences with mock values for testing.
This method is used to mock the initial state of the SharedPreferences
object used in tests. It takes a parameter of type Map<String, Object>
for which the key is used to identify the stored SharedPreferences
object and the value is the actual object stored in SharedPreferences
.
For instance:
If we want our SharedPreferences
object in our test to store the number 42 with the key counter
, we do it this way:
SharedPreferences.setMockInitialValues({'counter': 42});
Testing the getCounter() method
Test that the
getCount()
method returns 0 if there is no value stored inSharedPreferences
.We first call the
SharedPreferences.setMockInitialValues()
and pass it{}
(emptyMap
object) method to make sure nothing is stored inSharedPreferences
. We, then, pass it into theSharedPreferencesUtil
class.We, then, can call the
getCount()
method and compare it with the expected value of 0 using the expect() method from the test library.
import 'package:shared_preferences/shared_preferences.dart';
import 'package:shared_preferences_unit_tests_flutter/shared_preferences_util.dart';
import 'package:test/test.dart';
main() {
group(SharedPreferencesUtil, () {
group('getCounter', () {
test('returns 0 if no value is stored in SharedPreferences', () async {
SharedPreferences.setMockInitialValues({});
final SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
final SharedPreferencesUtil sharedPreferencesUtil =
SharedPreferencesUtil(sharedPreferences: sharedPreferences);
const expectedCounter = 0;
final actualCounter = sharedPreferencesUtil.getCount();
expect(expectedCounter, actualCounter);
});
});
});
}
Test that the
getCount()
method returns the correct value stored inSharedPreferences
.We first call
SharedPreferences.setMockInitialValues()
and pass it{SharedPreferencesUtil.countKey: counterValue}
whereSharedPreferencesUtil.counterKey
is the key andcounterValue
contains the value we want to store. We, then, pass it into theSharedPreferencesUtil
class.We, then, can call the
getCount()
method and compare it with the expected value of 0 using theexpect()
method.
import 'package:shared_preferences/shared_preferences.dart';
import 'package:shared_preferences_unit_tests_flutter/shared_preferences_util.dart';
import 'package:test/test.dart';
main() {
group(SharedPreferencesUtil, () {
group('getCounter', () {
test('returns 0 if no value is stored in SharedPreferences', () async {
...
});
test('returns the correct value stored in SharedPreferences', () async {
const counterValue = 42;
SharedPreferences.setMockInitialValues(
{SharedPreferencesUtil.countKey: counterValue});
final SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
final SharedPreferencesUtil sharedPreferencesUtil =
SharedPreferencesUtil(sharedPreferences: sharedPreferences);
const expectedCount = counterValue;
final actualCounter = sharedPreferencesUtil.getCount();
expect(expectedCount, actualCounter);
});
});
});
}
Testing the setCounter() method
Test that the
setCount()
method stores the correct value inSharedPreferences
.We first call the
SharedPreferences.setMockInitialValues()
and pass it{}
(emptyMap
object) method to make sure nothing is stored inSharedPreferences
. We, then, pass it into theSharedPreferencesUtil
class.We, then, can call the
SharedPreferences.getInt()
method, pass theSharedPreferencesUtil.countKey
key to it to get the value inSharedPreferences
compare it with the expected value in thecountValue
variable.
import 'package:shared_preferences/shared_preferences.dart';
import 'package:shared_preferences_unit_tests_flutter/shared_preferences_util.dart';
import 'package:test/test.dart';
main() {
group(SharedPreferencesUtil, () {
group('getCounter', () {
test('returns 0 if no value is stored in SharedPreferences', () async {
...
});
test('returns the correct value stored in SharedPreferences', () async {
...
});
});
group('setCounter', () {
test('stores the correct count value in SharedPreferences', () async {
SharedPreferences.setMockInitialValues({});
final SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
final SharedPreferencesUtil sharedPreferencesUtil =
SharedPreferencesUtil(sharedPreferences: sharedPreferences);
const countValue = 42;
sharedPreferencesUtil.setCount(countValue);
const expectedCounter = countValue;
final actualCounter =
sharedPreferences.getInt(SharedPreferencesUtil.countKey);
expect(expectedCounter, actualCounter);
});
});
});
}
Complete Test File
The content of the entire test file is shown below:
import 'package:shared_preferences/shared_preferences.dart';
import 'package:shared_preferences_unit_tests_flutter/shared_preferences_util.dart';
import 'package:test/test.dart';
main() {
group(SharedPreferencesUtil, () {
group('getCounter', () {
test('returns 0 if no value is stored in SharedPreferences', () async {
SharedPreferences.setMockInitialValues({});
final SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
final SharedPreferencesUtil sharedPreferencesUtil =
SharedPreferencesUtil(sharedPreferences: sharedPreferences);
const expectedCounter = 0;
final actualCounter = sharedPreferencesUtil.getCount();
expect(expectedCounter, actualCounter);
});
test('returns the correct value stored in SharedPreferences', () async {
const counterValue = 42;
SharedPreferences.setMockInitialValues(
{SharedPreferencesUtil.countKey: counterValue});
final SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
final SharedPreferencesUtil sharedPreferencesUtil =
SharedPreferencesUtil(sharedPreferences: sharedPreferences);
const expectedCount = counterValue;
final actualCounter = sharedPreferencesUtil.getCount();
expect(expectedCount, actualCounter);
});
});
group('setCounter', () {
test('stores the correct count value in SharedPreferences', () async {
SharedPreferences.setMockInitialValues({});
final SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
final SharedPreferencesUtil sharedPreferencesUtil =
SharedPreferencesUtil(sharedPreferences: sharedPreferences);
const countValue = 42;
sharedPreferencesUtil.setCount(countValue);
const expectedCounter = countValue;
final actualCounter =
sharedPreferences.getInt(SharedPreferencesUtil.countKey);
expect(expectedCounter, actualCounter);
});
});
});
}
Conclusion
Mocking the SharedPreferences
object in tests makes use of the setMockInitialValues
method to initialize the state.
The complete code can be found on GitHub.