【问题标题】:Mock repository method failed verify test模拟存储库方法验证测试失败
【发布时间】:2021-03-16 01:04:47
【问题描述】:

我在 .NET Core 应用程序中使用 Moq 框架和 xUnit。我有一个存储库的模拟

public interface IItemRepository<T>
{
    string Add(T entity);
}

我想测试使用这个存储库的类的方法

public DefaultCartService(IItemRepository<CartItem> cartRepository)
{
    _cartRepository = cartRepository;
}

public Task<GenericResponse<string>> AddItem(CartItem model)
{
   var result = new GenericResponse<string>();

    try
    {
        result.Response = _cartRepository.Add(cartItem);
    }
    catch(Exception ex)
    {
        result.Status = false;
        result.Error = ex.Message;
    }

    return Task.FromResult(result);
}

这是一个用于包装存储库结果的通用响应类

public class GenericResponse<T>
{
    public bool Status { get; set; } = true;
    public T Response { get; set; }
    public string Error { get; set;
    }
}

这就是我为存储库预设 Mock 并调用方法的方式

[Fact]
public  void AddItem_WorkingTest()
{
    //creating mock
    var mock = new Mock<IItemRepository<CartItem>>();

    //setting a method
    mock.Setup(x => x.Add(new CartItem())).Returns("SomeGuidValue");

    //creating input param
    CartItemInputModelDTO inputModel = new CartItem() {BuyerId = "232", ProductId = "35435" };

    //creating service class instance and passing repository mock
    var _service = new DefaultCartService(_cartRepository.Object);

    //calling method
    var result =  _service.AddItem(inputModel).Result.Response;

    //verifying that mocks method been called
    mock.Verify(x => x.Add(new CartItem()), Times.AtLeastOnce);
}

因此,我的测试失败,因为从未调用过存储库。而且我不明白为什么,因为我设置了没有要调用的停止方法 测试结果

Moq.MockException : 对模拟的预期调用至少一次, 但从未执行过:x =&gt; x.Add(CartItem)
执行的调用: Mock&lt;IItemRepository&lt;CartItem&gt;:2 (X): 未执行任何调用。

【问题讨论】:

    标签: .net-core moq xunit


    【解决方案1】:

    在设置中使用It.IsAny&lt;CartItem&gt;()。当前设置不起作用,因为在测试中通过的实例不是设置中使用的实例。

    另外,如果测试返回 Task 派生结果的成员,则使测试异步

    [Fact]
    public  async Task AddItem_WorkingTest() {
        //creating mock
        var mock = new Mock<IItemRepository<CartItem>>();
    
        //setting a method
        mock.Setup(x => x.Add(It.IsAny<CartItem>())).Returns("SomeGuidValue");
    
        //creating input param
        var inputModel = new CartItem() {BuyerId = "232", ProductId = "35435" };
    
        //creating service class instance and passing repository mock
        var _service = new DefaultCartService(mock.Object);
    
        //calling method
        var result =  await _service.AddItem(inputModel);;
    
        //verifying that mocks method been called
        mock.Verify(x => x.Add(It.IsAny<CartItem>()), Times.AtLeastOnce);
    }
    

    如果您想验证传递给模拟的实例成员,请使用带有谓词的It.Is&lt;CartItem&gt;()

    例如

    //... omitted for brevity
    
    mock.Verify(x => x.Add(It.Is<CartItem>(_ => 
        _.BuyerId == inputModel.BuyerId 
        && _.ProductId == inputModel.ProductId)), Times.AtLeastOnce);
    

    参考Moq Quickstart

    【讨论】:

    • 我唯一没有得到的东西,为什么这不起作用var item = It.IsAny&lt;CartItem&gt;(); mock.Setup(x =&gt; x.Add(item)).Returns("qwe"); var _service = new DefaultCartService(mock.Object); mock.Verify(x =&gt; x.Add(item), Times.AtLeastOnce);它在设置和验证中使用相同的模型。
    • @MikhailSloushch It.* 只能在表达式中直接使用。它不能用作局部变量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-24
    相关资源
    最近更新 更多