我有一个定义返回Future的方法的类。 “未来”包含一个同样返回未来的类列表。
class User{
Future<List<Album>> albums(){
};
}
class Album{
Future<List<Photos>> photos(){
}
};
在测试另一个类时,在这些类中模拟方法的最佳方法是什么?
我尝试测试的课程看起来有点像
class Presenter {
Presenter( User user){
user.albums().then( _processAlbums);
}
_processAlbums(List<Album> albums) {
albums.forEach( (album)=>album.photos.then( _processPhotos));
}
_processPhotos(List<Photo> photos) {
....stuff
}
}
我尝试过编写像这样的单元测试
class MockUser extends Mock implements User{}
class MockAlbum extends Mock implements Album{}
class MockPhoto extends Mock implements Photo{}
class MockFutureList<T> extends Mock implements Future<T>{
MockFutureList( List<T> items){
when( callsTo( "then")).thenReturn( items);
}
}
void main(){
test("constuctor should request the albums from the user ",(){
MockUser user = new MockUser();
MockAlbum album = new MockAlbum();
List<Album> listOfAlbums = [ album];
MockPhoto photo = new MockPhoto();
List<Album> listOfPhotos = [ album];
user.when( callsTo( "albums")).thenReturn( new MockFutureList(listOfAlbums));
album.when( callsTo( "photos")).thenReturn( new MockFutureList( listOfPhotos));
PicasaPhotoPresentor underTest = new PicasaPhotoPresentor( view, user);
user.getLogs( callsTo( "albums")).verify( happenedOnce);
album.getLogs( callsTo( "photos")).verify( happenedOnce);
});
}
这允许我测试构造函数调用user.photos()方法,但不是调用了album.photos()方法。
我不确定嘲笑未来是个好主意 - 创建一个包含Mocks列表的'真实'未来会不会更好?
任何想法都会非常有用!
答案 0 :(得分:1)
由于您只想验证调用User
和Album
中的方法,因此您无需模拟Future
。
验证模拟在这里有点棘手,因为你在构造函数中链接了未来。由于对event loop在Dart中的工作方式有一点了解,我建议您在创建演示者后使用未来并调用expectAsync
。
expectAsync
函数告诉单元测试库等待它被调用以验证您的测试。否则测试将成功完成,而不会满足您的期望。
有了这个,这就是你的测试应该是什么样的:
import 'package:unittest/unittest.dart';
class MockUser extends Mock implements User {}
class MockAlbum extends Mock implements Album {}
void main() {
test("constuctor should request the albums from the user ", () {
var user = new MockUser();
var album = new MockAlbum();
user.when(callsTo("albums")).thenReturn(new Future(() => [album]));
var presenter = new PicasaPhotoPresentor(view, user);
// Verify the mocks on the next event loop.
new Future(expectAsync(() {
album.getLogs(callsTo("photos")).verify(happendOnce);
}));
});
}
答案 1 :(得分:0)
这是我设法做到的
1)定义FutureCallbackMock
class FutureCallbackMock extends Mock implements Function {
Future<void> call();
}
2)从模拟中获取功能并进行设置
FutureCallback onPressed = FutureCallbackMock().call;
completer = Completer<void>();
future = completer.future;
when(onPressed()).thenAnswer((_) => future);
3)像这样验证
verify(onPressed()).called(1);
4)如果需要,请完成未来:
completer.complete();
注意:在颤动测试中,我必须像这样将测试包在tester.runAsync
中
testWidgets(
'when tapped disables underlying button until future completes',
(WidgetTester tester) async {
await tester.runAsync(() async {
// test here
});
});