【发布时间】:2013-05-22 04:04:06
【问题描述】:
在一个项目中,我正在尝试使用正则表达式来区分各种类型的句子并将它们映射到处理这些句子的函数。
这些句子处理函数中的大多数都从句子本身获取参数,由正则表达式中的捕获组解析出来。
例如:“我为 2 个 cookie 支付了 20 美元”与我的解析树(字典)中的一个正则表达式匹配。正则表达式将提取 20 美元作为组“价格”,将 2 匹配为组“金额”。目前我正在映射到正确的 Handler 函数并按如下方式调用它:
foreach(KeyValuePair<Regex, Type> pair in sentenceTypes)
{
Match match = pair.Key.Match(text);
if(match.Success)
{
IHandler handler = handlerFactory.CreateHandler(pair.Value);
output = handler.Handle(match);
}
}
简单处理程序类的示例。
public class NoteCookiePriceHandler
{
public string Handle(Match match)
{
double payment = Convert.ToDouble(match.Result("${payment}"));
int amount = Convert.ToInt32(match.Result("${amount}"));
double price = payment / amount;
return "The price is $" + price;
}
}
当我意识到我实际上无法模拟 Match 对象或 Regex 时,我正试图使用 Moq 设置一些单元测试来提供帮助。仔细想想,总体而言,设计似乎有些缺陷,因为我依赖于正确解析命名组并将其传递给没有良好接口的 Handler 类。
我正在寻找有关更有效设计的建议,以便将参数正确传递给映射的处理程序函数/类,因为传递 Match 对象似乎有问题。
如果做不到这一点,任何帮助找出有效模拟 Regex 或 Match 的方法将不胜感激,至少可以帮助我解决我的短期问题。它们都缺少默认构造函数,因此我很难让 Moq 创建它们的对象。
编辑:我最终通过为我的匹配组传递一个字符串字典,而不是(un-Moq-able)匹配对象本身来解决至少模拟问题。我对这个解决方案不是特别满意,因此我们仍将不胜感激。
foreach(KeyValuePair<Regex, Type> pair in sentenceTypes)
{
match = pair.Key.Match(text);
if(match.Success)
{
IHandler handler= handlerFactory.CreateHandler(pair.Value);
foreach (string groupName in pair.Key.GetGroupNames())
{
matchGroups.Add(groupName, match.Groups[groupName].Value);
}
interpretation = handler.Handle(matchGroups);
【问题讨论】:
-
我猜你正在对 Handle(match match) 函数进行单元测试。传递一个 IMatch 接口然后使用 Moq.Mock 存根方法怎么样?
-
也许您应该以类层次结构的形式为解析器输出声明分类,然后将处理程序插入层次结构(例如 Dictionary
)。这将允许您让一个处理程序通过将其与句子类型层次结构中的某个中间节点相关联来处理多种类型的句子。当被要求处理一个句子时,寻找它的类型的处理程序,如果没有定义,寻找基本类型的处理程序等等 - 并且可能将通用错误处理程序与根(你的抽象 Sentence 类)相关联。 -
听起来像是一个有趣的实验!
-
也许您可以在 this site 等网站中测试您的正则表达式。因为模拟你的比赛会导致它迭代到下一个值
标签: c# regex unit-testing moq