Moq - 验证具有参数值的方法调用

发布于 2024-10-21 04:40:33 字数 889 浏览 1 评论 0原文

我正在尝试使用 Moq 测试调用具有“params”列表的方法,但由于某种原因,此方法失败了。方法签名是这样的:

void AttachAsModifiedToOrders(IOrder order, params 
       Expression<Func<IOrder, object>>[] modifiedProperties);

然后在模拟设置中,我做了类似的事情,从模拟集合中执行简单的“删除/插入”操作:

MockEntities.Setup(n => n.AttachAsModifiedToOrders(It.IsAny<DataAccess.Order>()))
    .Callback<IOrder, Expression<Func<IOrder, object>>[]>((order, expr) => 
      { Orders.Remove(Orders.Where(o => o.Id== order.Id).First()); 
      Orders.Add((DataAccess.Order)order); });

最后,验证:

MockEntities.Verify(x => x.AttachAsModifiedToOrders(It.IsAny<Order>(), 
     It.IsAny<Expression<Func<IOrder, object>>>()), Times.Exactly(1));

我已经检查过,代码执行正常并且该方法被调用(模拟的方法),但验证失败。我错过了什么吗?或者只是 Moq 不支持这个“params”调用?

I'm trying to test with Moq that a method that has a "params" list is called, but for some reason this is failing. The method signature is something like this :

void AttachAsModifiedToOrders(IOrder order, params 
       Expression<Func<IOrder, object>>[] modifiedProperties);

Then in the Mock setup i've done something like this to do a simple "remove / insert" from the mocked collection :

MockEntities.Setup(n => n.AttachAsModifiedToOrders(It.IsAny<DataAccess.Order>()))
    .Callback<IOrder, Expression<Func<IOrder, object>>[]>((order, expr) => 
      { Orders.Remove(Orders.Where(o => o.Id== order.Id).First()); 
      Orders.Add((DataAccess.Order)order); });

Finally, the verification :

MockEntities.Verify(x => x.AttachAsModifiedToOrders(It.IsAny<Order>(), 
     It.IsAny<Expression<Func<IOrder, object>>>()), Times.Exactly(1));

I've checked, and the code executes ok and the method is called (the mocked one), but the verification is failing. am i missing something? or is it just that this "params" call is not supported by Moq?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无法回应 2024-10-28 04:40:33

我很难复制这个。我认为您的验证中有一个拼写错误:

MockEntities.Verify(x => x.AttachAsModifiedToOrders(It.IsAny<Order>(), It.IsAny<Expression<Func<IOrder, object>>>()), Times.Exactly(1));

应该是:

MockEntities.Verify(x => x.AttachAsModifiedToOrders(It.IsAny<Order>(), It.IsAny<Expression<Func<IOrder, object[]>>>()), Times.Exactly(1));

我还想知道第一个 It.IsAny 是否应该是接口而不是具体类型?

然而,这是对某些功能的过于复杂的测试,并且代码示例缺少一些部分,例如 DataAccess 类型或类实例(不确定?)、Order 和 Orders。

为了解决这个问题,我创建了 IOrder 接口和一个使用该接口的操纵器对象,这有点荒谬,但它驱动了测试:

public interface IOrder
{
    void AttachAsModifiedToOrders(IOrder order, params Expression<Func<IOrder, object[]>>[] modifiedProperties);

}

public class Manipulator
{
    public Manipulator(IOrder order)
    {
        Expression<Func<IOrder, object[]>> exp = o => new object[0];
        order.AttachAsModifiedToOrders(order, exp);
    }

    public void DoStuff() { }
}

然后我创建了一个测试装置来验证参数 arg:

[TestFixture]
public class Tester
{
    [Test]
    public void Test()
    {
        var order = new Mock<IOrder>();
        order.Setup(n => n.AttachAsModifiedToOrders(It.IsAny<IOrder>()));

        var manipulator = new Manipulator(order.Object);
        manipulator.DoStuff();

        order.Verify(x => x.AttachAsModifiedToOrders(It.IsAny<IOrder>(), It.IsAny<Expression<Func<IOrder, object[]>>>()), Times.Once());
    }
}

这对我有用,所以我不这样做不认为问题直接出在参数值和起订量上。我确实认为您最好退后一步,看看您是否真的对与 Mock 交互的类进行单元测试,或者尝试验证几种不同类型的集成用法。参数和表达式树也有点异味。

I had difficulty replicating this. I think there's a typo in your verify:

MockEntities.Verify(x => x.AttachAsModifiedToOrders(It.IsAny<Order>(), It.IsAny<Expression<Func<IOrder, object>>>()), Times.Exactly(1));

Should be:

MockEntities.Verify(x => x.AttachAsModifiedToOrders(It.IsAny<Order>(), It.IsAny<Expression<Func<IOrder, object[]>>>()), Times.Exactly(1));

I also wonder if the first It.IsAny should be the interface and not the concrete type?

However, this is a overly-complicated test of some bit of functionality, and the code sample is missing a few pieces, like the DataAccess type or class instance (not sure?), Order, and Orders.

To work around that, I created the IOrder interface and a manipulator object that uses the interface, its a bit nonsensical, but it drives the test:

public interface IOrder
{
    void AttachAsModifiedToOrders(IOrder order, params Expression<Func<IOrder, object[]>>[] modifiedProperties);

}

public class Manipulator
{
    public Manipulator(IOrder order)
    {
        Expression<Func<IOrder, object[]>> exp = o => new object[0];
        order.AttachAsModifiedToOrders(order, exp);
    }

    public void DoStuff() { }
}

I then created a test fixture to validate the params arg:

[TestFixture]
public class Tester
{
    [Test]
    public void Test()
    {
        var order = new Mock<IOrder>();
        order.Setup(n => n.AttachAsModifiedToOrders(It.IsAny<IOrder>()));

        var manipulator = new Manipulator(order.Object);
        manipulator.DoStuff();

        order.Verify(x => x.AttachAsModifiedToOrders(It.IsAny<IOrder>(), It.IsAny<Expression<Func<IOrder, object[]>>>()), Times.Once());
    }
}

This works for me, so I don't think the problem is the params value and Moq directly. I do think you'd be well off to take a step back and see if you are really unit testing the class that interacts with the Mock, or trying to verify integrated usages of a couple different types. The params and expression tree is a bit of a smell also.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文