web-dev-qa-db-fra.com

Comment se moquer d'une méthode statique en flutter avec Mockito?

J'ai un fichier une fonction fetchPosts() qui est chargé de recevoir de nouveaux messages d'un serveur et de les stocker dans une base de données SQLite locale.

Comme recommandé sur le SQFLITE DOC , je stocke une seule référence à ma base de données.

Voici le contenu de mon fichier database.Dart:

import 'Dart:async';
import 'package:path/path.Dart';
import 'package:sqflite/sqflite.Dart';

class DBProvider {
  DBProvider._();
  static final DBProvider db = DBProvider._();

  static Database _database;

  static Future<Database> get database async {
    if (_database != null) return _database;
    // if _database is null, we instantiate it
    _database = await _initDB();
    return _database;
  }

  static Future<Database> _initDB() async {
    final dbPath = await getDatabasesPath();
    String path = join(dbPath, 'demo.db');

    return await openDatabase(path, version: 1, onCreate: _onCreate);
  }

  static Future<String> insert(String table, Map<String, dynamic> values) async { /* insert the record*/ }

  // Other functions like update, delete etc.
}

Ensuite, je l'utilise comme tel dans mon fichier fetchPosts.Dart

import 'Dart:convert';
import 'package:http/http.Dart' as http;
import '../services/database.Dart';

const url = 'https://myapp.herokuapp.com';

Future<void> fetchPosts() {
  final client = http.Client();
  return fetchPostsUsingClient(client);
}

Future<void> fetchPostsUsingClient(http.Client client) async {
  final res = await client.get(url);
  final posts await Post.fromJson(json.decode(response.body));

  for (var i = 0; i < posts.length; i++) {
    await DBProvider.insert('posts', posts[i]);
  }
}

Dans mon test, comment puis-je verify que DBProvider.insert() a été appelée?

fetchPosts_test.Dart

import 'package:test/test.Dart';
import 'package:http/http.Dart' as http;
import 'package:mockito/mockito.Dart';
import 'package:../services/fetchPosts.Dart';

// Create a MockClient using the Mock class provided by the Mockito package.
// Create new instances of this class in each test.
class MockClient extends Mock implements http.Client {}

void main() {
  group('fetchPosts', () {
    test('update local db', () async {
      final client = MockClient();

      // Use Mockito to return a successful response when it calls the provided http.Client.
      when(client.get()).thenAnswer((_) async => http.Response('{"title": "Test"}', 200));

      await fetchPostsWithClient(client);

      verify(/* DBProvider.insert has been called ?*/);
    });
  });
}
8
Gpack

Finalement, je devais réécrire mon database.Dart Pour le rendre testable/moqueur.
[.____] Voici le nouveau fichier:

import 'Dart:async';
import 'package:path/path.Dart';
import 'package:sqflite/sqflite.Dart';

class DBProvider {
  static final DBProvider _singleton = DBProvider._internal();

  factory DBProvider() {
    return _singleton;
  }

  DBProvider._internal();

  static Database _db;

  static Future<Database> _getDatabase() async {
    if (_db != null) return _db;
    // if _database is null, we instantiate it
    _db = await _initDB();
    return _db;
  }

  static Future<Database> _initDB() async {
    final dbPath = await getDatabasesPath();
    String path = join(dbPath, 'demo.db');

    return openDatabase(path, version: 1, onCreate: _onCreate);
  }

  Future<String> insert(String table, Map<String, dynamic> values) async {
    final db = await _getDatabase();
    return db.insert(table, values);
  }

  // ...
}

Maintenant, je peux utiliser le même tour que avec le http.client. Merci @ rémirousselet

3
Gpack