当向 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));
这最终使所有测试用例都通过了。
我正在为各种测试用例设置 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));
这最终使所有测试用例都通过了。