带有包装数组的测试流
Test stream with wrapped array
我正在尝试测试函数 emitArray
发出一个 Response.Success
其值为 ['test']
.
如果我发出 List<String>
一切都按预期工作,但是一旦我将结果列表包装在 Response<List<String>>
中,测试就会失败。
结果发出,但与预期结果比较失败。
我想知道它是否与 Response.Success
中 ==
的实现有关,我使用的是 IDE 提供的默认实现。
这不是我的真实代码,它只是一个更容易理解的简单示例,用于尝试找出问题。
这是我要测试的class:
class ListResponse {
final _array = BehaviorSubject<Response<List<String>>>();
Stream<Response<List<String>>> get array => _array.stream;
Future<void> emitArray() async {
_array.add(Response.success(['test']));
}
void dispose() {
_array.close();
}
}
这是我的测试:
void main() {
ListResponse underTest;
setUp(() {
underTest = ListResponse();
});
test('It should emit array', () {
final array = Response.success(['test']);
expect(
underTest.array,
emitsInOrder([
array,
emitsDone,
]),
);
underTest.emitArray();
underTest.dispose();
});
}
这是它抛出的错误:
Expected: should do the following in order:
• emit an event that SuccessResponse<List<String>>:<SuccessResponse{value: [test]}>
• be done
Actual: <Instance of 'BehaviorSubject<Response<List<String>>>'>
Which: emitted • SuccessResponse{value: [test]}
x Stream closed.
which didn't emit an event that SuccessResponse<List<String>>:<SuccessResponse{value: [test]}>
这是回应class
class Response<T> {
Response._();
factory Response.success(T value) = SuccessResponse<T>;
factory Response.error(Exception error) = ErrorResponse<T>;
}
class ErrorResponse<T> extends Response<T> {
ErrorResponse(this.error): super._();
final Exception error;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ErrorResponse &&
runtimeType == other.runtimeType &&
error == other.error;
@override
int get hashCode => error.hashCode;
@override
String toString() {
return 'ErrorResponse{error: $error}';
}
}
class SuccessResponse<T> extends Response<T> {
SuccessResponse(this.value): super._();
final T value;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is SuccessResponse &&
runtimeType == other.runtimeType &&
value == other.value;
@override
int get hashCode => value.hashCode;
@override
String toString() {
return 'SuccessResponse{value: $value}';
}
}
I'm wondering if it's related to the implementation of == in Response.Success
没错。此特定测试失败,因为您无法将列表与 ==
:
进行比较
abstract class List<E> implements EfficientLengthIterable<E> {
...
/**
* Whether this list is equal to [other].
*
* Lists are, by default, only equal to themselves.
* Even if [other] is also a list, the equality comparison
* does not compare the elements of the two lists.
*/
bool operator ==(Object other);
}
作为解决方法,您可以更改实现以比较对象的字符串表示形式:
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is SuccessResponse &&
runtimeType == other.runtimeType &&
value.toString() == other.value.toString();
有趣的是,传递未包装的 List<String>
s 对象通过了测试。发生这种情况是因为 StreamMatcher
使用 matcher
包中的 equals()
来匹配事件,并且 equals()
can match lists and maps。它首先尝试匹配 ==
的对象,然后检查它们是否是 Iterable/Set/Map (并递归地深度匹配它们),然后报告不匹配错误。
我正在尝试测试函数 emitArray
发出一个 Response.Success
其值为 ['test']
.
如果我发出 List<String>
一切都按预期工作,但是一旦我将结果列表包装在 Response<List<String>>
中,测试就会失败。
结果发出,但与预期结果比较失败。
我想知道它是否与 Response.Success
中 ==
的实现有关,我使用的是 IDE 提供的默认实现。
这不是我的真实代码,它只是一个更容易理解的简单示例,用于尝试找出问题。
这是我要测试的class:
class ListResponse {
final _array = BehaviorSubject<Response<List<String>>>();
Stream<Response<List<String>>> get array => _array.stream;
Future<void> emitArray() async {
_array.add(Response.success(['test']));
}
void dispose() {
_array.close();
}
}
这是我的测试:
void main() {
ListResponse underTest;
setUp(() {
underTest = ListResponse();
});
test('It should emit array', () {
final array = Response.success(['test']);
expect(
underTest.array,
emitsInOrder([
array,
emitsDone,
]),
);
underTest.emitArray();
underTest.dispose();
});
}
这是它抛出的错误:
Expected: should do the following in order:
• emit an event that SuccessResponse<List<String>>:<SuccessResponse{value: [test]}>
• be done
Actual: <Instance of 'BehaviorSubject<Response<List<String>>>'>
Which: emitted • SuccessResponse{value: [test]}
x Stream closed.
which didn't emit an event that SuccessResponse<List<String>>:<SuccessResponse{value: [test]}>
这是回应class
class Response<T> {
Response._();
factory Response.success(T value) = SuccessResponse<T>;
factory Response.error(Exception error) = ErrorResponse<T>;
}
class ErrorResponse<T> extends Response<T> {
ErrorResponse(this.error): super._();
final Exception error;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ErrorResponse &&
runtimeType == other.runtimeType &&
error == other.error;
@override
int get hashCode => error.hashCode;
@override
String toString() {
return 'ErrorResponse{error: $error}';
}
}
class SuccessResponse<T> extends Response<T> {
SuccessResponse(this.value): super._();
final T value;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is SuccessResponse &&
runtimeType == other.runtimeType &&
value == other.value;
@override
int get hashCode => value.hashCode;
@override
String toString() {
return 'SuccessResponse{value: $value}';
}
}
I'm wondering if it's related to the implementation of == in Response.Success
没错。此特定测试失败,因为您无法将列表与 ==
:
abstract class List<E> implements EfficientLengthIterable<E> {
...
/**
* Whether this list is equal to [other].
*
* Lists are, by default, only equal to themselves.
* Even if [other] is also a list, the equality comparison
* does not compare the elements of the two lists.
*/
bool operator ==(Object other);
}
作为解决方法,您可以更改实现以比较对象的字符串表示形式:
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is SuccessResponse &&
runtimeType == other.runtimeType &&
value.toString() == other.value.toString();
有趣的是,传递未包装的 List<String>
s 对象通过了测试。发生这种情况是因为 StreamMatcher
使用 matcher
包中的 equals()
来匹配事件,并且 equals()
can match lists and maps。它首先尝试匹配 ==
的对象,然后检查它们是否是 Iterable/Set/Map (并递归地深度匹配它们),然后报告不匹配错误。