A month of Flutter: Stream transforms and failing tests
Tags: flutter, tutorial, testing
Published: 2018-12-13 02:51:50

_Originally published on [bendyworks.com](https://bendyworks.com/blog/a-month-of-flutter-stream-transforms-and-failing-tests)._

Now that I've got a [Post model with mock data](https://bendyworks.com/blog/a-month-of-flutter-post-model-and-mock-data) and a [StreamBuilder for rendering](https://bendyworks.com/blog/a-month-of-flutter-rendering-a-list-view-with-stream-builder), it all needs to be wired together.

The main changes I'm making are in `_MyHomePageState` where I'm replacing the stream of `int`s with a call to the new `_loadPosts` method.

~~~dart
Stream<List<Post>> _loadPosts(BuildContext context) {
  return DefaultAssetBundle.of(context)
      .loadString('assets/posts.json')
      .then<List<dynamic>>((String value) => json.decode(value))
      .asStream()
      .map(_convertToPosts);
}
~~~

`_loadPosts` uses [`DefaultAssetBundle.of`](https://docs.flutter.io/flutter/widgets/DefaultAssetBundle/of.html) to get the most appropriate [`AssetBundle`](https://docs.flutter.io/flutter/services/AssetBundle-class.html) for loading files from the `assets` directory.

Reading the `String` contents of a file is asynchronous, after which the JSON contents can be decoded. The loading and decoding will happen as a `Future` but I want to be working on a stream so I'll use [`asStream`](https://api.dartlang.org/stable/2.1.0/dart-async/Future/asStream.html) to convert the `Future` to a `Stream`.

Finally the Stream will then get transformed using [`map`](https://api.dartlang.org/stable/2.1.0/dart-async/Stream/map.html) and another new method `_convertToPosts`.

~~~dart
List<Post> _convertToPosts(List<dynamic> data) {
  return data.map((dynamic item) => Post.fromMap(item)).toList();
}
~~~

Every time an event comes down the stream, `map` will call the convert method on the value. In this case the value is a `List` of items and `List`'s [`map`](https://api.dartlang.org/stable/2.1.0/dart-core/Iterable/map.html) will pass each item to `Post.fromMap`. Note that `map` on a `List` is different from `map` on a `Stream`. `map` on a `List` is lazy so we'll force it to execute with a final [`toList`](https://api.dartlang.org/stable/2.1.0/dart-core/Iterable/toList.html).

The rest of the changes are going thought the code base and updating `List<int>` types to be `List<Post>` types and passing `Post` instances into the rendering `PostItem`s. I'll also replace the hard coded `'Prim Birb'` text with the dynamic `username` from the `Post` instances.

![Screenshot of rendered mock usernames](https://thepracticaldev.s3.amazonaws.com/i/lmfoehbinrds1zn7kvaw.png)

As I was updating the tests to use the new mock JSON data, I kept running into failures. I was seeing tests timing out or the `PostsList` error handling showing errors instead of content. After some digging it turns out that the code in `testWidgets` [can't access](https://github.com/flutter/flutter/issues/8490) files or assets. With [CI configured](https://bendyworks.com/blog/a-month-of-flutter-configuring-continuous-integration) I can't merge code without passing tests so come back tomorrow to see how I fix them.

## Code changes

- [#29 Turn mock posts into Stream](https://github.com/abraham/birb/pull/29)