与Moq的Xunit和Mock数据
我是单元测试新手,任何人都可以建议如何使用xUnit和Moq测试下面的公共方法(CreateUser),谢谢!
public async Task<bool> CreateUser(UserDTO newUser)
{
newUser.CustomerId = _userResolverService.GetCustomerId();
if (await CheckUserExists(newUser)) return false;
var salt = GenerateSalt(10);
var passwordHash = GenerateHash(newUser.Password, salt);
await _usersRepository.AddAsync(new User()
{
Role = newUser.Role,
CretedOn = DateTime.Now,
CustomerId = newUser.CustomerId,
Email = newUser.Email,
FirstName = newUser.FirstName,
LastName = newUser.LastName,
PasswordHash = passwordHash,
Salt = salt,
UpdatedOn = DateTime.Now
});
return true;
}
下面的私有方法检查用户是否存在只返回现有用户的数量
private async Task<bool> CheckUserExists(UserDTO user)
{
var users = await _usersRepository.GetAllAsync();
var userCount = users.Count(u => u.Email == user.Email);
return userCount > 0;
}
哈希生成
private static string GenerateHash(string input, string salt)
{
var bytes = System.Text.Encoding.UTF8.GetBytes(input + salt);
var sha256 = SHA256.Create();
var hash = sha256.ComputeHash(bytes);
return ByteArrayToString(hash);
}
盐生成
private static string GenerateSalt(int size)
{
var rng = RandomNumberGenerator.Create();
var buff = new byte[size];
rng.GetBytes(buff);
return Convert.ToBase64String(buff);
}
private static string ByteArrayToString(byte[] ba)
{
var hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
谢谢,J
编辑1
这是我到目前为止:
[Fact]
public async void CreateUser_True()
{
//arrange
var dataSource = new Mock<IRepository<User, int>>();
var userResolverService = new Mock<IUserResolverService>();
var tokenService = new Mock<ITokenService>();
var users = new List<User>();
users.Add(new User()
{
Email = "test@test.com",
CustomerId = 1
});
dataSource.Setup(m => m.GetAllAsync()).ReturnsAsync(users); // Error Here with converting async task to IEnumerable...
var accountService = new AccountService(dataSource.Object,userResolverService.Object,tokenService.Object);
//act
//assert
}
主要的问题是我不知道如何模拟,建立私人方法“CheckUserExists”的行为,因为它调用IRepository被嘲笑为类,所以在这种情况下,将这个私有方法返回我的模拟设置为GetAllAsync?
编辑2
public async Task<TEntity> AddAsync(TEntity entity)
{
if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}
_entities.Add(entity);
await _context.SaveChangesAsync();
return entity;
}
编辑3
[Fact]
public async void CreateUser_True()
{
//arrange
var users = new List<User>();
users.Add(new User()
{
Email = "test@test.com",
CustomerId = 1
});
_dataSource.Setup(m => m.GetAllAsync()).ReturnsAsync(users);
_dataSource.Setup(m => m.AddAsync(It.IsAny<User>())).Returns<User>(Task.FromResult);
var accountService = new AccountService(_dataSource.Object, _userResolverService.Object, _tokenService.Object);
//act
var result = await accountService.CreateUser(new UserDTO()
{
Email = "truetest@test.com"
});
var updatedUsersList = await _dataSource.Object.GetAllAsync();
var usersCount = updatedUsersList.Count();
//assert
Assert.True(result);
Assert.Equal(2, usersCount);
}
由于要测试的方法是异步的,因此需要设置所有异步依赖关系以允许方法流程完成。 至于私有方法,您希望设置在该方法中使用的任何依赖项的行为,在这种情况下是用户存储库。
[Fact]
public async Task CreateUser_True() {
//arrange
var usersRepository = new Mock<IRepository<User, int>>();
var userResolverService = new Mock<IUserResolverService>();
var tokenService = new Mock<ITokenService>();
var user = new User() {
Email = "test@test.com",
CustomerId = 1
};
var users = new List<User>() { user };
usersRepository.Setup(_ => _.GetAllAsync()).ReturnsAsync(users);
usersRepository.Setup(_ => _.AddAsync(It.IsAny<User>()))
.Returns<User>(arg => Task.FromResult(arg)) //<-- returning the input value from task.
.Callback<User>(arg => users.Add(arg)); //<-- use call back to perform function
userResolverService.Setup(_ => _.GetCustomerId()).Returns(2);
var accountService = new AccountService(usersRepository.Object, userResolverService.Object, tokenService.Object);
//act
var actual = await accountService.CreateUser(new UserDto {
Email = "email@example.com",
Password = "monkey123",
//...other code removed for brevity
});
//assert
Assert.IsTrue(actual);
Assert.IsTrue(users.Count == 2);
Assert.IsTrue(users.Any(u => u.CustomerId == 2);
}
阅读Moq Quickstart以更好地了解如何使用模拟框架。
链接地址: http://www.djcxy.com/p/35349.html