私はユニットテストが初めてです。以下のパブリックメソッド(CreateUser)をxUnitとMoqを使用してテストする方法を誰かにアドバイスできます。ありがとう!
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 = "[email protected]",
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 = "[email protected]",
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 = "[email protected]"
});
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 = "[email protected]",
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 protected]",
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 を読んで、モックフレームワークの使用方法をよりよく理解してください。