@@ -31,6 +31,11 @@ Rultor.com](https://www.rultor.com/b/dartoos-dev/json_cache)](https://www.rultor
3131 - [ JsonCacheLocalStorage — LocalStorage] ( #jsoncachelocalstorage )
3232 - [ JsonCacheHive — Hive] ( #jsoncachehive )
3333 - [ JsonCacheCrossLocalStorage — CrossLocalStorage] ( #jsoncachecrosslocalstorage )
34+ - [ Unit Test Tips] ( #unit-test-tips )
35+ - [ Suggested Dependency Relationship] ( #suggested-dependency-relationship )
36+ - [ Using Fake Implementation] ( #using-fake-implementation )
37+ - [ Widget Testing] ( #widget-testing )
38+ - [ Example of Widget Test Code] ( #example-of-widget-test-code )
3439- [ Demo application] ( #demo-application )
3540- [ Contribute] ( #contribute )
3641- [ References] ( #references )
@@ -256,7 +261,80 @@ is an implementation on top of the
256261 …
257262 final LocalStorageInterface prefs = await LocalStorage.getInstance();
258263 final JsonCache jsonCache = JsonCacheMem(JsonCacheCrossLocalStorage(prefs));
259- …
264+ ```
265+
266+ ## Unit Test Tips
267+
268+ This package has been designed with unit testing in mind. This is one of the
269+ reasons for the existence of the ` JsonCache ` interface.
270+
271+ ### Suggested Dependency Relationship
272+
273+ Whenever a function, method, or class needs to interact with user data, it
274+ should do so via a reference to the ` JsonCache ` interface rather than relying on
275+ an actual implementation.
276+
277+ See the code snippet below:
278+
279+ ``` dart
280+ /// Stores/retrieves user data from the device's local storage.
281+ class JsonCacheRepository implements ILocalRepository {
282+ /// Sets the [JsonCache] instance.
283+ const JsonCacheRepository(this._cache);
284+ // This class depends on an interface rather than any actual implementation
285+ final JsonCache _cache;
286+
287+ /// Retrieves a cached email by [userId] or `null` if not found.
288+ @override
289+ Future<String?> getUserEmail(String userId) async {
290+ final userData = await _cache.value(userId);
291+ if (userData != null) {
292+ // the email value or null if absent.
293+ return userData['email'] as String?;
294+ }
295+ // There is no data associated with [userId].
296+ return null;
297+ }
298+ }
299+ ```
300+
301+ By depending on an interface rather than an actual implementation, the code
302+ above is [ loosely coupled] ( https://en.wikipedia.org/wiki/Loose_coupling ) to this
303+ package — which means it's easy to test as you can
304+ [ mock] ( https://docs.flutter.dev/cookbook/testing/unit/mocking ) the ` JsonCache `
305+ dependency.
306+
307+ ### Using Fake Implementation
308+
309+ In addition to mocking, there is another approach to unit testing: making use of
310+ a 'fake' implementation. Usually this so called 'fake' implementation provides
311+ the functionality required by the ` JsonCache ` interface without touching the
312+ device's local storage. An example of this implementation is the
313+ [ JsonCacheFake] ( https://pub.dev/documentation/json_cache/latest/json_cache/JsonCacheFake-class.html )
314+ class — whose sole purpose is to help developers with unit tests.
315+
316+ ### Widget Testing
317+
318+ Because of the asynchronous nature of dealing with cached data, you're better
319+ off putting all your test code inside a ` tester.runAsync ` method; otherwise,
320+ your test case may stall due to a
321+ [ deadlock] ( https://en.wikipedia.org/wiki/Deadlock ) caused by a [ race
322+ condition] ( https://stackoverflow.com/questions/34510/what-is-a-race-condition )
323+ as there might be multiple ` Futures ` trying to access the same resources.
324+
325+ #### Example of Widget Test Code
326+
327+ Your widget test code should look similar to the following code snippet:
328+
329+ ``` dart
330+ testWidgets('refresh cached value', (WidgetTester tester) async {
331+ final LocalStorage localStorage = LocalStorage('my_cached_data');
332+ final jsonCache = JsonCacheMem(JsonCacheLocalStorage(localStorage));
333+ tester.runAsync(() async {
334+ // asynchronous code inside runAsync.
335+ await jsonCache.refresh('test', <String, dynamic>{'aKey': 'aValue'});
336+ });
337+ });
260338```
261339
262340## Demo application
@@ -293,5 +371,4 @@ Make sure the command below **passes** before making a Pull Request.
293371
294372## References
295373
296- - [ Caching for objects] ( https://www.pragmaticobjects.com/chapters/012_caching_for_objects.html )
297374- [ Dart and race conditions] ( https://pub.dev/packages/mutex )
0 commit comments