flutter - Dart、Flutter Redux Thunk 单元测试
问题描述
我已经编写了以下代码,并试图在颤振中测试一个 redux thunk 动作。不幸的是,当我调试代码时,我可以看到 thunkMiddleware 没有按预期拦截操作(因为返回的Function(store)
永远不会被触发)。
state.dart
@JsonSerialize()
class Pokemon {
final String name;
final String url;
Pokemon(this.name, this.url);
factory Pokemon.fromJson(Map<String, dynamic> json) =>
_$PokemonFromJson(json);
}
// state
@immutable
class PokemonsState {
final List<Pokemon> pokemons;
final bool isLoading;
final Exception ex;
const PokemonsState(
{this.pokemons = const [], this.isLoading = false, this.ex});
PokemonsState copyWith(
{List<Pokemon> pokemons, bool isLoading, Exception ex}) {
return PokemonsState(
pokemons: pokemons ?? this.pokemons,
isLoading: isLoading ?? this.isLoading,
ex: ex ?? this.ex);
}
}
// reducer
PokemonsState pokemonsState(PokemonsState state, action) {
switch (action.runtimeType) {
case FetchPokemons:
return state.copyWith(isLoading: true);
case AddPokemons:
if (action.error == null)
return state.copyWith(
pokemons: action.payload, isLoading: false, ex: null);
return state.copyWith(ex: action.error, isLoading: false);
}
return state;
}
// actions
class FetchPokemons {}
class AddPokemons {
final List<Pokemon> payload;
final Exception error;
AddPokemons({this.payload, this.error});
}
// thunks
loadPokemons(Client client) {
return (Store<AppState> store) async {
store.dispatch(FetchPokemons());
try {
var res = await client.get(pokemonUrl);
if (res.statusCode == HttpStatus.ok) {
final pokemons = jsonDecode(res.body)['results'];
store.dispatch(AddPokemons(
payload:
List<Pokemon>.from(pokemons.map((i) => Pokemon.fromJson(i)))));
} else {
throw HttpException(res.reasonPhrase);
}
} on Exception catch (e) {
store.dispatch(AddPokemons(error: e));
}
};
}
state_test.dart
class MockClient extends Mock implements Client{}
void main(){
Store<PokemonsState> store;
setUp(() {
store = Store(pokemonsState,
initialState: PokemonsState(), middleware: [thunkMiddleware]);
});
test('add Pokemons success should add a list of pokemons to the store',
() {
final client = MockClient();
when(client.get(argThat(isInstanceOf<String>()))).thenAnswer((_) async =>
Response(
'{"results": [{"name": "p1", "url": "u1"}, {"name": "p2", "url": "u2"}]}',
200));
store.dispatch(loadPokemons(client));
expect(store.state.pokemons.length, 2);
});
});
}
任何修复测试的帮助将不胜感激!
解决方案
我遇到了同样的问题。这是我的解决方案:
void main() {
Store<AppState> store;
setUp(() {
store = Store(
appStateReducer,
initialState: AppState.initialState(),
middleware: [thunkMiddleware],
);
});
test('', () async {
await store.dispatch(fetchLocalization());
expect(store.state.localization.get('WELCOME'), 'Welcome');
});
}
我确实创建了一个自定义appStateReducer
,但它绑定到不进行任何 http 调用的操作。
这里是:
class SetLocalization {
final Map<String, String> values;
SetLocalization(this.values);
}
ThunkAction<AppState> fetchLocalization() {
return (Store<AppState> store) async {
var localization = await _LocalizationApi().read();
store.dispatch(SetLocalization(localization));
};
}
// used to fake http call
class _LocalizationApi {
final Map<String, String> data = {
'WELCOME': 'WECLOME',
'WELCOME_MESSAGE': 'Welcome'
};
Future<Map<String, String>> read() async => data;
}
推荐阅读
- haskell - 无法使用 cabal 安装 Random 模块?(哈斯克尔)
- firebase - Firebase 存储/gcloud 存储不适用于 Unity 资源包
- javascript - 打字稿:如何在另一个数组的对象数组中设置值
- pouchdb - 如何从尚未同步的远程更新特定对象?
- excel - 在excel中使用数组和索引公式获取单元格值
- rspec - 如何配置 Aptana 3 IDE 来为我的 Rails 项目运行 rspec 测试?
- app-store - 暗模式 AppStore 政策
- javascript - 如何在三个js中多次高效渲染一个网格?
- c++ - 由于日志而导致程序阻塞
- python - 如何在bash中将前缀组合到ls的输出?