简体   繁体   English

即使在同一方法调用上同时验证Times.Once()和Times.Never()时,Moq测试也会通过

[英]Moq test passes even when verifying both Times.Once() and Times.Never() on same method call

I'm using Xunit to test the Create method on my CarController and I'm using Moq to mock my CarRepository . 我正在使用Xunit在我的CarController上测试Create方法,我正在使用Moq来模拟我的CarRepository

I'm then using mockCarRepository.Verify(m => m.Create(It.IsAny<Car>()), Times.Once()); 然后我使用mockCarRepository.Verify(m => m.Create(It.IsAny<Car>()), Times.Once()); to check that the Create method on my repository is being called. 检查是否正在调用我的存储库上的Create方法。 However the test passes irrespective of whether I call it or not. 然而,无论我是否打电话,测试都会通过。

Here is a complete example where I verify both that Create is called once AND that it is called never . 这是一个完整的示例,我验证both that Create is called once AND that it is called never My test passes when I would have expected it to fail. 当我预料到失败时,我的测试通过了。

using System;
using Moq;
using Xunit;
namespace Test
{
    public class CarTest
    {
        [Fact()]
        public async void CreateTest()
        {
            var mockCarRepository = new Mock<CarRepository>();
            var carController = new CarController(mockCarRepository.Object);
            carController.Create(new Car
            {
                Make = "Aston Martin",
                Model = "DB5"
            });
            mockCarRepository.Verify(m => m.Create(It.IsAny<Car>()), Times.Once());
            mockCarRepository.Verify(m => m.Create(It.IsAny<Car>()), Times.Never());
        }
    }

    public class CarController
    {
        private readonly CarRepository _repo;
        public CarController(CarRepository repo)
        {
            _repo = repo;
        }

        public void Create(Car car)
        {
            _repo.Create(car);
        }
    }

    public class Car
    {
        public virtual String Make { get; set; }
        public virtual String Model { get; set; }
    }

    public class CarRepository
    {
        public virtual void Create(Car car)
        {
            // DO SOMETHING
        }
    }
}

When I debug the test, although it still passes, I notice that the following exception is thrown: 当我调试测试时,虽然它仍然通过,但我注意到抛出了以下异常:

A first chance exception of type 'Moq.MockException' occurred in Moq.dll

Additional information: 

Expected invocation on the mock should never have been performed, but was 1 times: m => m.Create(It.IsAny<Car>())

No setups configured.



Performed invocations:

CarRepository.Create(Test.Car)

The exception is expected as I am calling Create once and verifying Times.Never() but I would like my test to fail. 我正在调用Create一次并验证Times.Never()但我希望我的测试失败。 What do I need to do to achieve this? 我需要做什么才能实现这一目标?

Update It turns out that the problem was that I'd marked my test as async - removing that causes it to pass. 更新事实证明问题是我将我的测试标记为async - 删除导致它通过。 However the actual code I'm writing will call an async method, so my question is now, how can I verify methods are called when using asynchronous methods? 但是我写的实际代码会调用async方法,所以现在我的问题是,如何在使用异步方法时验证方法是否被调用?

See the answer here for an explanation of why async void test methods do not work in xUnit. 请参阅此处的答案了解为什么async void测试方法在xUnit中不起作用的解释。

The solution is to give your test method an async Task signature. 解决方案是为您的测试方法提供async Task签名。

async void functionality has been added ready for version 2.0 of xunit, see here for details. 已经为xunit 2.0版添加了async void功能,有关详细信息,请参阅此处

事实证明,问题是我的测试方法被标记为async删除,导致它按预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM