0

我正在对一些与存储库交互的代码进行单元测试,该代码采用表达式 ( Expression<Func<Entity, bool>>) 来过滤结果,如下所示:

int orderId = 10;

_respository.GetFiltered(order => order.Id == orderId);

我遇到了单元测试问题,更具体地说,是设置表达式将匹配的期望。在单元测试中,我想这样做:

_mockRespository.Setup(r => r.GetFiltered(order => order.Id == 10)).Returns(new Order[0]).AtMostOnce();

我找到了一个解决方案,建议.ToString()对每个表达式执行并进行比较,但是当您引用诸如 orderId 之类的变量时,表达式完全不同!

人们在做什么来测试这个?

谢谢,

大卫

4

1 回答 1

0

我想说这在一定程度上是您真正想要通过单元测试验证的问题,这归结为您的单元测试理念。

我们所做的是,当在存储库协作者(未在测试中)上调用 GetFoo() 时,我们不一定要验证从类型 A(测试中)传递的 linq 到实体表达式参数是否使用特定的表达式树。对于单元测试,我们满足于验证 GetFoo() 方法是否调用了正确的签名。

在您的情况下,您似乎正在使用 Moq (?),在这种情况下会变成这样(注意语法混乱)

_mockRespository.Setup(r => r.GetFiltered(It.IsAny<Expression<Func<Entity, bool>>>())).Returns(new Order[0]).AtMostOnce();

对我们来说,这是有道理的,因为 a) 模拟方法参数表达式树比较验证确实很痛苦 b) 即使我们可以验证该参数,B 实际上如何解释参数值的不同组合可能会改变(如合约 A 的语义->B) 如果是这样的话,会使测试变得脆弱。

我们使用自动化故事测试来测试生产 A 和生产 B 之间的交互。我们认为这是测试这些场景的更好方法,因为它们通常类似于“根据表达式 X 过滤存储中的所有 A 并给我所有符合条件的对象”匹配'。对我们来说,这是有道理的,因为集成测试(通常一两个快乐的案例就足够了)。

如果这对您来说还不够,我会阅读 a)如何创建自定义 Moq 匹配器,尽管我不能肯定地说有一个简单的解决方案(很可能有)或 b)设置期望回调因此您可以捕获参数并在测试后对其进行检查。像这样的东西:

    Expression<Func<Entity, bool>> actualExpression = null;
    _mockRespository.Setup(r => r.GetFiltered(It.IsAny<Expression<Func<Entity, bool>>>())).Returns(new Order[0]).AtMostOnce().Callback((Expression<Func<Entity, bool>> expr => { actualExpression = expr});

    // exercise production code

    Assert.IsTrue(actualExpression ...... someithing clever here);

注意:以上所有代码都是在堆栈溢出编辑器中编写的。如果它不编译,不要追究我的责任,起订量文档涵盖了这一点

于 2011-08-18T15:14:18.020 回答