为什么这个 Moq 是这样的? NUnit 测试失败?

发布于 2024-08-29 05:08:06 字数 1087 浏览 2 评论 0原文

我有这个 dataAccess 模拟对象,我试图验证它的方法之一是否正在被调用,以及传递到该方法中的参数是否满足某些约束。据我所知,该方法确实被调用,并且满足了约束。这行测试抛出 MockException:

data.Verify(d => d.InsertInvoice(It.Is<Invoice>(i => i.TermPaymentAmount == 0m)), Times.Once());

但是,删除约束并接受任何发票会通过测试:

data.Verify(d => d.InsertInvoice(It.IsAny<Invoice>()), Times.Once());

我创建了一个测试窗口窗体来实例化此测试类,运行其 .Setup() 方法,然后调用我想要测试的方法。我在模拟对象未通过测试以实际悬停在发票上的代码行上插入一个断点

data.InsertInvoice(invoice);

,并且我可以确认其 .TermPaymentAmount 十进制属性在方法执行时确实为零调用。

出于绝望,我什至添加了对我的 dataAccess 模拟的回调:

data.Setup(d => d.InsertInvoice(It.IsAny<Invoice>())).Callback((Invoice inv) => MessageBox.Show(inv.TermPaymentAmount.ToString("G17")));

这给了我一个显示 0 的消息框。这真的让我很困惑,我店里的其他人都无法弄清楚这一点。任何帮助将不胜感激。

一个几乎不相关的问题,我可能应该独立问,是使用 Mock.Verify() (像我在这里那样)还是使用 Mock.Expect() 更好>。可验证后跟 Mock.VerifyAll() 就像我看到其他人做的那样?如果答案是视情况而定,那么哪些情况下需要使用其中一种而不是另一种?

I have this dataAccess mock object and I'm trying to verify that one of its methods is being invoked, and that the argument passed into this method fulfills certain constraints. As best I can tell, this method is indeed being invoked, and with the constraints fulfilled. This line of the test throws a MockException:

data.Verify(d => d.InsertInvoice(It.Is<Invoice>(i => i.TermPaymentAmount == 0m)), Times.Once());

However, removing the constraint and accepting any invoice passes the test:

data.Verify(d => d.InsertInvoice(It.IsAny<Invoice>()), Times.Once());

I've created a test windows form that instantiates this test class, runs its .Setup() method, and then calls the method which I am wishing to test. I insert a breakpoint on the line of code where the mock object is failing the test

data.InsertInvoice(invoice);

to actually hover over the invoice, and I can confirm that its .TermPaymentAmount decimal property is indeed zero at the time the method is invoked.

Out of desperation, I even added a call back to my dataAccess mock:

data.Setup(d => d.InsertInvoice(It.IsAny<Invoice>())).Callback((Invoice inv) => MessageBox.Show(inv.TermPaymentAmount.ToString("G17")));

And this gives me a message box showing 0. This is really baffling me, and no one else in my shop has been able to figure this out. Any help would be appreciated.

A barely related question, which I should probably ask independently, is whether it is preferable to use Mock.Verify() as I have here, or to use Mock.Expect(). Verifiable followed by Mock.VerifyAll() as I have seen other people doing? If the answer is situational, which situations would warrent the use of one over the other?

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

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

发布评论

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

评论(3

夜灵血窟げ 2024-09-05 05:08:06

只是为了排除这种情况(因为我有一些像你一样的奇怪行为:
尝试 Times.Exactly(1) 而不是 Times.Once()。
使用 Times.Once() 时发生了一些奇怪的事情
不过,我猜想 Once() 在内部使用 Exactly(1) ......

Just to rule this out (because I've got some strange behavior like you :
Try Times.Exactly(1) instead of Times.Once().
I've had some weird thing happening when using Times.Once()
Though, I would have guessed that Once() is using Exactly(1) internally...

小伙你站住 2024-09-05 05:08:06

我使用的是 Moq 3.1.0.0 版本,并且在以下测试用例中没有遇到此问题。

internal class Program
{
    private static void Main(string[] args)
    {
        var mock = new Mock<IData>();
        mock.Setup(d => d.InsertInvoice(It.IsAny<Invoice>()));

        var service = new MyService(mock.Object);
        service.DoSomething(new Invoice());

        mock.Verify(d => d.InsertInvoice(It.Is<Invoice>(i => i.TermPaymentAmount == 0m)), Times.Once());

        Console.ReadLine();
    }
}

internal class MyService
{
    private readonly IData _data;

    public MyService(IData data)
    {
        _data = data;
    }

    public void DoSomething(Invoice invoice)
    {
        _data.InsertInvoice(invoice);
    }
}

public class Invoice
{
    public decimal TermPaymentAmount { get; set; }
}

public interface IData
{
    void InsertInvoice(Invoice invoice);
}

您能否提供更多有关如何使用模拟的信息?

I am using version 3.1.0.0 of Moq and am not experiencing this issue with the following test case.

internal class Program
{
    private static void Main(string[] args)
    {
        var mock = new Mock<IData>();
        mock.Setup(d => d.InsertInvoice(It.IsAny<Invoice>()));

        var service = new MyService(mock.Object);
        service.DoSomething(new Invoice());

        mock.Verify(d => d.InsertInvoice(It.Is<Invoice>(i => i.TermPaymentAmount == 0m)), Times.Once());

        Console.ReadLine();
    }
}

internal class MyService
{
    private readonly IData _data;

    public MyService(IData data)
    {
        _data = data;
    }

    public void DoSomething(Invoice invoice)
    {
        _data.InsertInvoice(invoice);
    }
}

public class Invoice
{
    public decimal TermPaymentAmount { get; set; }
}

public interface IData
{
    void InsertInvoice(Invoice invoice);
}

Could you supply maybe a bit more information on how you are using the mock?

半山落雨半山空 2024-09-05 05:08:06

我的猜测是,这可能与浮点值的等效性检查固有的问题有关。您的 Invoice.TermPaymentAmount 属性值可能是计算结果吗?

要了解我在说什么,请参阅这个可能相关的问题:
安全吗检查浮点值是否等于 0?

My guess is that it may have something to do with the problems inherent with equivalency checking of floating point values. Is your Invoice.TermPaymentAmount property value the result of a calculation, perhaps?

For an idea of what I'm talking about, see this possibly related question:
Is it safe to check floating point values for equality to 0?

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