dartdart-asyncdart-unittest

Dart - how to mock a method that returns a future


I have a class that defines a method that returns a Future. The Future contains a list of class that also return a future.

    class User{
      Future<List<Album>> albums(){

      };
    }
    class Album{
      Future<List<Photos>> photos(){
      }
    };

What is the best way to mock the method in these classes when testing another class?

The class I am trying to test looks a bit like

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

I tried writing a unit test like this

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

  });
}

This allowed me to test that the constructor called the user.photos() method, but not that the album.photos() method was called.

I am not sure that mocking a Future is a good idea - Would it not be better to create a 'real' Future that contains a list of Mocks?

Any ideas would be very helpful!


Solution

  • You can do this:

    when(mock.method()).thenAnswer((_) => Future.value('string'));