tour test started learn how unit-testing dart

unit testing - test - ¿Cómo debo probar un futuro en Dart?



test dart (5)

Como alternativa, esto es lo que he estado haciendo. Es similar a las respuestas anteriores:

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); });

Recibo una referencia al futuro y coloco todas mis declaraciones de expectativa dentro de la llamada. Luego, registro una expect(future, completes) para asegurar que realmente se complete.

¿Cómo se puede probar un método que devuelve Future antes de que se complete el corredor de prueba? Tengo un problema donde mi corredor de prueba de unidad se completa antes de que se completen los métodos asíncronos.


Consulte la sección sobre pruebas asíncronas en este article o la documentación de la API para expectAsync .

A continuación se muestra un breve ejemplo. Tenga en cuenta que se debe llamar a expectAsync () antes de que el cierre pase a test () devuelve.

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); }); }

Otra forma de esperar a que se complete un futuro durante una prueba es devolverlo desde el cierre pasado a la función de prueba. Vea este ejemplo del artículo vinculado anteriormente:

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)); }); }); }


El ejemplo completo de cómo probar con el emparejador de completion es el siguiente.

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}))); }); }

Es posible que el corredor de prueba de la unidad no se complete antes de que se complete este código. Por lo que parece que la prueba unitaria se ejecutó correctamente. Con los Future que pueden tardar más tiempo en completarse de la manera correcta es utilizar el emparejador de completion disponible en el paquete unittest.

/** * 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));

Uno estaría tentado de hacer lo siguiente, lo que sería una forma incorrecta de probar un futuro devuelto en un dardo. ADVERTENCIA: a continuación hay una forma incorrecta de probar futuros.

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"]); }); }); }


Otra posibilidad es usar la función expectAsync1. El análogo de trabajo para la variante incorrecta inicial de la prueba sería:

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"]); })); }); }

Una ventaja del uso de expectAsync1 para las pruebas asíncronas es su capacidad de composición. A veces las pruebas naturalmente necesitan varios bloques de código asíncronos secuenciales. Prueba de muestra de 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(); })); }

Actualizar:

Tanto las API Future y unittest se cambiaron desde la pregunta inicial. Ahora es posible simplemente volver al Future desde la función de prueba y unittest lo ejecutó correctamente con todas las funciones asíncronas protegidas. Combinado con el hecho de que ahora se combinan la chain y then métodos de Future que proporcionan una buena sintaxis para las pruebas con varios bloques de código secuenciales. En la versión actual de mongo_dart, la misma prueba parece:

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(); }); }


Para mockito v. 2+ existe la posibilidad de hacerlo con la ayuda de

await untilCalled(mockObject.someMethod())