我正在try 模拟一个方法,该方法具有在抽象类中实现的泛型返回类型.

抽象类编码:

public abstract class AbstractRepository<T> where T : class
{
    protected virtual async Task<T> GetById(int id)
    {
        // some code
    }
}

实施类:

public class UserRepository : AbstractRepository<User>
{
    public Task<User> GetUserById(int id)
    {
        return base.GetById(id);
    }
}

测试方法:

[Theory]
public async Task GetUserById_UserExists_ReturnsUser(User user)
{
    Mock<UserRepository> mockRealSut = new(MockBehavior.Strict, new object[] {
    })
    {
        CallBase = true
    };

    //Setup Mock
    
    //Act
    User result = await mockRealSut.Object.GetUserById(1);
}

    

我无法成功设置Mock,因为实际的抽象方法总是被调用.

我try 了两种方法:

方法1:

_ = mockRealSut.Protected().Setup<Task<User>>("GetById", ItExpr.IsAny<int>()).ReturnsAsync(user);       

方法2:

public interface IGetByIdMethodMock<T>
{
    Task<T> GetById(int id);
}

_ = mockRealSut.Protected().As<IGetByIdMethodMock<User>>().Setup(m => m.GetById(It.IsAny<int>())).ReturnsAsync(user);

这篇关于Stackoverflow的帖子here似乎表明,方法2)应该有效,但它特定于泛型参数,而不是泛型返回类型.

我已经查看了MOQ文档,但我找不到解决此问题的方案.

我错过什么了吗? 我认为这应该是可能的与Moq,但有些东西是失踪,我找不到的问题.

这种类型的CRUD方法非常常见,所以如果Moq不涵盖这种类型的代码,那就太奇怪了.

推荐答案

问题是GetUserById方法调用base.GetById:

return base.GetById(id);

这意味着它显式调用AbstractRepository<User>.GetById,而不是UserRepository.GetById.

当你要求MOQ重写UserRepository.GetById时,你就这么做了,但你没有重写AbstractRepository<User>.GetById.

GetUserById方法更改为:

public Task<User> GetUserById(int id)
{
    return GetById(id);
}

然后,这样的测试就会奏效:

[Theory]
[InlineData(1)]
[InlineData(2)]
public async Task GetUserById(int id)
{
    var expected = new User();
    var repo = new Mock<UserRepository>();
    repo.Protected()
        .Setup<Task<User>>("GetById", ItExpr.Is<int>(i => i == id))
        .ReturnsAsync(expected);

    var actual = await repo.Object.GetUserById(id);

    Assert.Equal(expected, actual);
}

.net相关问答推荐

从Couchbase删除_txn文档的推荐方法?""

[x.x.x,)在Packages.lock.json依赖项中是什么意思?

Azure SignalR 和微服务

Puppeteer LaunchAsync 在未打开浏览器的情况下挂起

竖线在 PropertyGroup .csproj 文件中的含义

向从 .NET 序列化的对象添加 Xml 属性

dotnet ef dbcontext scaffold command --data-annotations 或 -d 命令行参数似乎不起作用

您如何确定两个 HashSet 是否相等(按值,而不是按引用)?

编译时禁用 Dll 文化文件夹

您是否使用 TestInitialize 或测试类构造函数来准备每个测试?为什么?

将笔画应用于 WPF 中的文本块

msbuild,定义条件编译符号

将双精度转换为带有 N 个小数的字符串,点作为小数分隔符,并且没有千位分隔符

[DllImport("QCall")] 是什么?

何时在 C#/.NET 中使用指针?

POCO 是什么意思?

Moq - 不可覆盖的成员不能用于设置/验证表达式

如何获得 Bin 路径?

我应该如何删除 DbSet 中的所有元素?

.NET 图形库?