Testing Flutter apps翻譯-使用 Mockito 模擬依賴項

翻譯首頁web

在某些狀況下,單元測試依賴的類可能從實時Web服務或數據庫中獲取數據。這時可能很不方便,緣由以下:數據庫

  • 調用實時服務或數據庫會減慢測試的執行速度。
  • 若是Web服務或數據庫返回意外結果,則曾經經過的測試可能會失敗。這被稱爲「不可靠的測試」。
  • 很難使用實時Web服務或數據庫測試全部可能的成功和失敗場景。

因此,與其依賴實時的web服務或者數據庫,不如你「mock」這些依賴。mock容許咱們模擬一個實時的web服務或者數據庫而且根據狀況返回特定結果。json

通常來講,你能夠經過建立類的替代實現來模擬依賴項。你能夠本身寫這些替代實現或者使用更便捷的Mockito package瀏覽器

下面的步驟講解了使用Mockito package的基礎操做,更多操做請查看Mockito package documentationbash

步驟

  1. 添加 mockito 和 test 依賴。
  2. 建立一個方法用來測試。
  3. 建立一個模擬http.Client的測試文件。
  4. 爲每一個條件編寫測試。
  5. 運行測試。

1. 添加 mockito 和 test 依賴。

要想使用 mockito package,你首先須要添加它和 flutter_testpubspec.yaml 文件裏,添加位置在dev_dependencies下面。服務器

你也可使用 http package,在dependencies下面添加該依賴便可。網絡

dependencies:
  http: <newest_version>
dev_dependencies:
  test: <newest_version>
  mockito: <newest_version>
複製代碼

2. 建立一個方法用來測試。

在本例中,你將對從Internet方法獲取數據的fetchpost函數進行單元測試。爲了測試這個函數,你須要作以下2點改變:async

  1. 提供一個http.Client參數給函數。這容許你根據狀況提供正確的http.Client。對於Flutter和服務端項目,你能夠提供http.IOClient。對於瀏覽器應用程序,你能夠提供http.BrowserClient。對於單元測試,你能夠提供模擬的http.Client。

2.使用提供的client從網絡獲取數據,而不是直接使用http.get方法,不然會很難模擬數據。ide

這個測試函數看起來應該是這樣的:函數

Future<Post> fetchPost(http.Client client) async {
  final response =
      await client.get('https://jsonplaceholder.typicode.com/posts/1');

  if (response.statusCode == 200) {
    // If the call to the server was successful, parse the JSON
    return Post.fromJson(json.decode(response.body));
  } else {
    // If that call was not successful, throw an error.
    throw Exception('Failed to load post');
  }
}
複製代碼

3. 建立一個模擬http.Client的測試文件。

下一步,建立一個測試文件和一個 MockClient 類。根據單元測試介紹中的建議,在根目錄的 test 文件夾下建立一個叫 fetch_post_test.dart 的文件。

這個 MockClient 類實現了 http.Client。這將容許你將 MockClient 做爲參數傳遞到 fetchPost 函數,而且容許你在每一個測試裏返回不一樣的結果。

// 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 {}

main() {
  // Tests go here
}
複製代碼

4. 爲每一個條件編寫測試。

若是你思考一下 fetchPost 函數,會想到它只能返回下面的2個結果中的一個:

  1. 若是獲取數據成功,會返回一個Post數據。
  2. 若是獲取數據失敗,會拋出一個異常。

所以,你想要測試這兩個結果。你可使用 MockClient 返回獲取數據成功的測試結果,也能夠返回一個獲取數據失敗的測試結果。

爲了實現這一點,咱們使用Mockito提供的when函數。

// 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 {}

main() {
  group('fetchPost', () {
    test('returns a Post if the http call completes successfully', () async {
      final client = MockClient();

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

      expect(await fetchPost(client), isInstanceOf<Post>());
    });

    test('throws an exception if the http call completes with an error', () {
      final client = MockClient();

      // Use Mockito to return an unsuccessful response when it calls the
      // provided http.Client.
      when(client.get('https://jsonplaceholder.typicode.com/posts/1'))
          .thenAnswer((_) async => http.Response('Not Found', 404));

      expect(fetchPost(client), throwsException);
    });
  });
}
複製代碼

5. 運行測試。

既然你如今寫好了fetchPost的單元測試,那麼就能夠運行它了。

dart test/fetch_post_test.dart
複製代碼

你也可使用單元測試介紹裏介紹過的你喜歡的編譯器裏運行測試

總結:

在這個例子裏,你已經學會了如何使用Mockito去測試依賴web服務器或者數據庫的函數或者類。這只是一個簡短的 Mockito library 和模擬概念的介紹。更多信息請查看 Mockito package

相關文章
相關標籤/搜索