我想定义匹配器以检查解析器是否可以接受字符串。我做到了,但感觉不舒服。
Dart unittest代码:
library test_parser;
import 'package:unittest/unittest.dart';
import '../lib/shark_parser.dart';
main() {
SharkParser parser;
setUp(() {
parser = new SharkParser();
});
tearDown(() {
parser = null;
});
group("paramType parser", () {
test("should accept valid types", () {
expect(parser.paramType(), accept("String"));
expect(parser.paramType(), accept("int"));
expect(parser.paramType(), accept("List"));
expect(parser.paramType(), accept("List<User>"));
});
test("should not accept invalid types", () {
expect(parser.paramType(), notAccept("#"));
expect(parser.paramType(), notAccept("0"));
expect(parser.paramType(), notAccept("String()"));
expect(parser.paramType(), notAccept("List< User >"));
});
});
}
自定义匹配器:
Matcher accept(String matchingString) => new AcceptMatcher(matchingString);
Matcher notAccept(String matchingString) => new NotAcceptMatcher(matchingString);
class NotAcceptMatcher extends Matcher {
String matchingString;
NotAcceptMatcher(this.matchingString);
bool matches(item, Map matchState) {
return !item.end().accept(matchingString);
}
Description describe(Description description) {
return description.add("parser not accept string: $matchingString");
}
Description describeMismatch(item, Description mismatchDescription,
Map matchState, bool verbose) {
mismatchDescription.add("accepts it");
return mismatchDescription;
}
}
class AcceptMatcher extends Matcher {
String matchingString;
AcceptMatcher(this.matchingString);
bool matches(item, Map matchState) {
return item.end().accept(matchingString);
}
Description describe(Description description) {
return description.add("parser accept string: $matchingString");
}
Description describeMismatch(item, Description mismatchDescription,
Map matchState, bool verbose) {
mismatchDescription.add("doesn't accept");
return mismatchDescription;
}
}
您可以看到我必须定义两个匹配器NotAcceptMatcher
和AcceptMatcher
。逻辑很相似,但我不知道如何简单。
还有其他更简单的解决方案吗?
答案 0 :(得分:2)
您可以使用isNot
匹配器反转accept
匹配器:
expect(parser.paramType(), isNot(accept("#")));
它看起来有点搞笑,所以你可以创建一个函数来执行它:
Matcher notAccept(String s) => isNot(accept(s));
expect(parser.paramType(), notAccept("#"));
描述可能无法完美阅读,但它可以为您节省一些工作。
Matchers可能看起来很冗长,但如果你想要,你可以通过删除一些类型注释和使用短变量名来使你的matcher定义更简洁一些。当我编写一个由框架调用的类或函数时,我发现这是一个很好的权衡,因为我并不担心为其他用户记录它。
class AcceptMatcher extends Matcher {
final acceptString;
AcceptMatcher(this.acceptString);
matches(item, _) => item.end().accept(acceptString);
describe(d) => d.add("parser accept string: $acceptString");
describeMismatch(item, d, _, __) => d..add("doesn't accept");
}
另一种选择是使用predicate
匹配器:
Matcher accept(String s) =>
predicate((i) => i.end().accept(s), "parser accepts $s");