如何測試在測試運行器完成之前返回Future
的方法?在我的單元測試運行器完成異步方法完成之前,我遇到了一個問題。我應該如何測試飛鏢中的未來?
回答
如何使用completion
匹配器進行測試的完整示例如下。
import 'package:unittest/unittest.dart';
class Compute {
Future<Map> sumIt(List<int> data) {
Completer completer = new Completer();
int sum = 0;
data.forEach((i) => sum += i);
completer.complete({"value" : sum});
return completer.future;
}
}
void main() {
test("testing a future",() {
Compute compute = new Compute();
Future<Map> future = compute.sumIt([1, 2, 3]);
expect(future, completion(equals({"value" : 6})));
});
}
在此代碼完成之前,單元測試運行器可能無法完成。所以看起來單元測試正確執行。使用Future
可能需要較長時間才能完成正確的方法,即使用unittest包中的completion
匹配器。
/**
* Matches a [Future] that completes succesfully with a value that matches
* [matcher]. Note that this creates an asynchronous expectation. The call to
* `expect()` that includes this will return immediately and execution will
* continue. Later, when the future completes, the actual expectation will run.
*
* To test that a Future completes with an exception, you can use [throws] and
* [throwsA].
*/
Matcher completion(matcher) => new _Completes(wrapMatcher(matcher));
有人會試圖做下面這將是單元測試飛鏢返回的未來的不正確的方式。警告:以下是測試期貨的不正確方法。
import 'package:unittest/unittest.dart';
class Compute {
Future<Map> sumIt(List<int> data) {
Completer completer = new Completer();
int sum = 0;
data.forEach((i) => sum+=i);
completer.complete({"value":sum});
return completer.future;
}
}
void main() {
test("testing a future",() {
Compute compute = new Compute();
compute.sumIt([1, 2, 3]).then((Map m) {
Expect.equals(true, m.containsKey("value"));
Expect.equals(6, m["value"]);
});
});
}
另一種可能性是使用expectAsync1函數。 工作類似物用於測試的初始不正確的變體將是:
使用expectAsync1爲異步測試void main() {
test("testing a future",() {
Compute compute = new Compute();
compute.sumIt([1, 2, 3]).then(expectAsync1((Map m) {
Expect.equals(true, m.containsKey("value"));
Expect.equals(6, m["value"]);
}));
});
}
一個優點是它的可組合性。有時測試自然需要幾個連續的異步代碼塊。從mongo_db 樣品測試:
testCursorGetMore(){
var res;
Db db = new Db('${DefaultUri}mongo_dart-test');
DbCollection collection;
int count = 0;
Cursor cursor;
db.open().chain(expectAsync1((c){
collection = db.collection('new_big_collection2');
collection.remove();
return db.getLastError();
})).chain(expectAsync1((_){
cursor = new Cursor(db,collection,where.limit(10));
return cursor.each((v){
count++;
});
})).chain(expectAsync1((dummy){
expect(count,0);
List toInsert = new List();
for (int n=0;n < 1000; n++){
toInsert.add({"a":n});
}
collection.insertAll(toInsert);
return db.getLastError();
})).chain(expectAsync1((_){
cursor = new Cursor(db,collection,where.limit(10));
return cursor.each((v)=>count++);
})).then(expectAsync1((v){
expect(count,1000);
expect(cursor.cursorId,0);
expect(cursor.state,Cursor.CLOSED);
collection.remove();
db.close();
}));
}
更新:
和將來輸入單元測試的API進行了更改,因爲問題是最初要求。 現在可以從測試函數返回Future
,並且unittest正確執行它,並具有所有異步防護功能。 結合chain
和then
方法Future
現在被合併,爲幾個連續的代碼塊提供了很好的語法測試。在當前版本的mongo_dart中,相同的測試看起來像:
Future testCursorGetMore(){
var res;
Db db = new Db('${DefaultUri}mongo_dart-test');
DbCollection collection;
int count = 0;
Cursor cursor;
return db.open().then((c){
collection = db.collection('new_big_collection2');
collection.remove();
return db.getLastError();
}).then((_){
cursor = new Cursor(db,collection,where.limit(10));
return cursor.forEach((v){
count++;
});
}).then((dummy){
expect(count,0);
List toInsert = new List();
for (int n=0;n < 1000; n++){
toInsert.add({"a":n});
}
collection.insertAll(toInsert);
return db.getLastError();
}).then((_){
cursor = new Cursor(db,collection,null);
return cursor.forEach((v)=>count++);
}).then((v){
expect(count,1000);
expect(cursor.cursorId,0);
expect(cursor.state,State.CLOSED);
collection.remove();
return db.close();
});
}
ExpectAsync也是有用的,當你需要測試沒前途的本身,而是一些對象更改的屬性 – Martynas
剛返回的未來也同樣適用於'設置()'和'拆解()'當他們有這樣的測試是執行一些異步代碼直到'setUp()'完成才執行。 –
作爲替代方案,這是我一直在做的。它類似於上述問題的答案:
test('get by keys',() {
Future future = asyncSetup().then((_) => store.getByKeys(["hello", "dart"]));
future.then((values) {
expect(values, hasLength(2));
expect(values.contains("world"), true);
expect(values.contains("is fun"), true);
});
expect(future, completes);
});
我得到未來的引用,並把我所有的期望then
調用中的語句。然後,我註冊一個expect(future, completes)
以確保它實際完成。
我也喜歡這個例子。我可以通過這種方式看到一個簡單的方法來推銷這個連鎖店。 –
請參閱此article中的異步測試部分或expectAsync的API文檔。
下面是一個簡單的例子。請注意,在傳遞給test()返回的閉包之前,必須調用expectAsync()。
import 'package:unittest/unittest.dart';
checkProgress() => print('Check progress called.');
main() {
test('Window timeout test',() {
var callback = expectAsync(checkProgress);
new Timer(new Duration(milliseconds:100), callback);
});
}
另一種方式來等待將來完成時的測試是從傳遞給測試功能關閉返回。從上面鏈接的文章中看到這個例子:
import 'dart:async';
import 'package:unittest/unittest.dart';
void main() {
test('test that time has passed',() {
var duration = const Duration(milliseconds: 200);
var time = new DateTime.now();
return new Future.delayed(duration).then((_) {
var delta = new DateTime.now().difference(time);
expect(delta, greaterThanOrEqualTo(duration));
});
});
}
對於mockito
V 2+有可能與
await untilCalled(mockObject.someMethod())
- 1. 使用未來的飛鏢
- 2. 飛鏢HttpRequest返回未來
- 3. 飛鏢單元測試應該失敗的例外
- 4. 在飛鏢中測試性能
- 5. 飛鏢的完成者和未來?
- 6. 飛鏢中的飛鏢websocket:io and dart:html
- 7. 如何設置飛鏢單元測試中的測試超時時間?
- 8. 飛鏢單元測試 - 始終通過
- 9. 使用聚合物飛鏢測試1.0
- 10. 飛鏢異步單元測試
- 11. 如何在角度飛鏢測試中觸發組件事件?
- 12. 如何在單元測試中訪問飛鏢班
- 13. 如何根據未來生產的飛鏢分配飛鏢中的期貨結果?
- 14. 飛鏢Web_Audio飛鏢1.6
- 15. 我應該如何測試?
- 16. 飛鏢中未定義的新圖像()
- 17. 飛鏢中的urlencoding
- 18. 飛鏢單元測試時,我如何始終如一地設置環境?
- 19. 飛鏢 - NumberFormat的
- 20. 對飛鏢中未來物體的迷惑 -
- 21. 如何使用angular2_material飛鏢
- 22. 如何旋轉飛鏢中的圖像?
- 23. 如何刪除飛鏢中的cookie
- 24. 如何替換飛鏢中的聽衆?
- 25. 角飛鏢教程第4節 - '未來未解決'
- 26. 我應該如何處理未修復的錯誤測試
- 27. 同步等待未來或流在飛鏢中完成
- 28. 我應該如何測試WebServiceTemplate(SpringWS)
- 29. 如何/我應該測試AES算法
- 30. Ruby + Rspec:我應該如何測試attr_accessor?
很大的幫助,做到這一點!也許你應該把你的答案中的錯誤代碼移到你的問題上。 –
這是什麼不正確? –
哎呀,我明白,第一個代碼段沒有工作...但它的工作原理。忘記我的評論,對不起。 –