当向 Returns() 提供不同的值时,最小起订量返回相同的结果

Moq Returning Same Result When Supplying Different Values To Returns()

我正在为各种测试用例设置 Mock:

[Test]
[TestCase(0)]
[TestCase(1)]
[TestCase(4)]
public async Task Get_ReturnsAllUsers(int userCount)
{
    // Arrange
    var users = UserRepositoryTests.GenerateUsers(userCount);
    var extensionWrapper = new Mock<IDbConnectionExtensionsWrapper>();
    extensionWrapper
        .Setup(ex => ex.Get<User>(It.IsAny<IDbConnection>(), It.IsAny<IDbTransaction>(), It.IsAny<int>()))
        .Returns(Task.FromResult(users));

    var connection = new Mock<IDbConnection>();
    connection
        .Setup(conn => conn.BeginTransaction())
        .Returns(new Mock<IDbTransaction>().Object);

    var repository = new UserRepository(connection.Object, extensionsWrapper.Object);

    var usersFromRepository = await repository.Get();

    Assert.AreEqual(userCount, usersFromRepository.Count());
}

GenerateUsers 长得像

private static IEnumerable<User> GenerateUsers(int count)
{
    using var crypto = new RNGCryptoServiceProvider();
    var salt = new byte[16];
    crypto.GetBytes(salt);
    
    var random = new Random();
    var users = new List<User>();
    for (var i = 0; i < count; i++)
    {
        users.Add(new User
        {
            Id = i,
            Username = Convert.ToString(i),
            Salt = salt,
            Hash = salt,
        });
    }

    return users;
}

相关的 repository 代码看起来像

public UserRepository(IDbConnection connection, IDbConnectionExtensionsWrapper wrapper)
{
    this.Connection = connection;
    this.ConnectionWrapper = wrapper;
}

public async Task<IEnumerable<User>> Get()
{
    var users = await this.ConnectionWrapper
        .Get<User>(this.Connection);

    return users;
}

终于IDbConnectionExtensionsWrapper.Get(...)

public async Task<IEnumerable<T>> Get<T>(
    IDbConnection connection,
    IDbTransaction? transaction = null,
    int? timeout = null)
    where T : class
    => await connection.GetAllAsync<T>(transaction, timeout);

其中 connection.GetAllAsync 属于 Dapper.Contrib.Extensions

我遇到的问题是只有第一个 TestCase 成功。每次调用 IDbConnectionExtensionsWrapper.Get return 都是一个空的可枚举,尽管我在每种情况下都设置了 return。

原来是类型不匹配让我不知所措。由于 IDbConnectionExtensionsWrapper.Get(...) 的签名采用 int? 并且我正在使用 It.IsAny<int>() 设置模拟,因此没有合适的方法调用(它从未被调用)。

模拟方法的正确方法是

extensionWrapper
    .Setup(ex => ex.Get<User>(It.IsAny<IDbConnection>(), It.IsAny<IDbTransaction?>(), It.IsAny<int?>()))
    .Returns(Task.FromResult(users));

这最终使所有测试用例都通过了。