我正在尝试对书面方法执行单元测试,但遇到问题。
这是我的 UnityConfig 类:
public class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterInstance(AutoMapperConfig.Initialize());
container.RegisterType<IActiveDirectoryUserService, ActiveDirectoryUserService>();
container.RegisterType<IUserRepository, InMemoryUserRepository>();
container.RegisterType<IUserService, UserService>();
}
}
测试方法:
public async Task RegisterAsync(string name, string email, string firstName, string lastName, string password)
{
var user = await _userRepository.GetBynameAsync(name);
if (user != null)
{
throw new Exception($"User {name} already exists.");
}
else
{
var ActiveDirectoryUser = await _ActiveDirectoryUserService.GetBynameAsync(name);
if (ActiveDirectoryUser == null)
{
throw new Exception($"User {name} does not exist in Active Directory");
}
else
{
var salt = new Guid().ToString("N");
user = new User(name, ActiveDirectoryUser.Email, ActiveDirectoryUser.FirstName, ActiveDirectoryUser.LastName, password, salt);
await _userRepository.AddAsync(user);
}
}
}
测试方法:
[Test]
public async Task Test()
{
var userRepositoryMock = new Mock<IUserRepository>();
var activeDirectoryUserMock = new Mock<IactiveDirectoryUserService>();
var mapperMock = new Mock<IMapper>();
var userService = new UserService(userRepositoryMock.Object, activeDirectoryUserMock.Object, mapperMock.Object);
await userService.RegisterAsync("name", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b2c7c1d7c0f2d7dfdbd3de9cd1dddf" rel="noreferrer noopener nofollow">[email protected]</a>", "first name", "last name", "password");
userRepositoryMock.Verify(x => x.AddAsync(It.IsAny<User>()), Times.Once);
}
经过测试的方法在测试之外工作正常,但是当我运行测试时它失败了。我在 Debug模式下运行测试,发现它没有进入
var user = await _userRepository.GetBynameAsync(name);
var ActiveDirectoryUser = await _ActiveDirectoryUserService.GetBynameAsync(name);
知道为什么它在测试期间不进入这些方法吗?我需要向 UnityConfig 添加一些条目才能使其正常工作吗?
--编辑
private static ISet<User> _users = new HashSet<User>
{
new User("user1", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e58487a59788848c89cb868a88" rel="noreferrer noopener nofollow">[email protected]</a>", "firstnam1", "lastname1", "pass", "salt"),
new User("user2", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a0c1c3e0d2cdc1c9cc8ec3cfcd" rel="noreferrer noopener nofollow">[email protected]</a>", "firstnam2", "lastname2", "pass", "salt"),
new User("user3", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a9c8cde9dbc4c8c0c587cac6c4" rel="noreferrer noopener nofollow">[email protected]</a>", "firstnam3", "lastname3", "pass", "salt")
};
public async Task<IEnumerable<User>> GetAllAsync()
=> await Task.FromResult(_users);
最佳答案
发生的情况是模拟不知道如何从异步调用返回,因此当代码尝试等待它们时它会失败。它不一定与您的 DI 容器有关。此单元测试中不存在它。
由于没有提供有关测试中使用的类型的足够信息,因此做出一些假设。
鉴于正在测试的方法,让我们假设您有这样的界面
public interface IUserRepository {
Task<User> GetByNameAsync(string name);
Task AddAsync(User user);
}
public interface IActiveDirectoryUserService {
Task<AdUserAccount> GetByNameAsync(string name);
}
public class AdUserAccount {
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
注意返回任务
的方法。
您需要设置模拟以了解如何处理异步调用并允许任务顺利完成。
[Test]
public async Task Test() {
//Arrrange
var name = "name";
var email = "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="493c3a2c3b092c24202825672a2624" rel="noreferrer noopener nofollow">[email protected]</a>";
var firstname = "first name";
var lastname = "last name";
var userRepositoryMock = new Mock<IUserRepository>();
//Testing that it returns no user for that name so return null from async call
userRepositoryMock.Setup(_ => _.GetByNameAsync(name)).ReturnsAsync((User)null);
//Need this to make sure async call runs to completion
userRepositoryMock.Setup(_ => _.AddAsync(It.IsAny<User>())).Returns(Task.FromResult((object)null));
var activeDirectoryUserMock = new Mock<IActiveDirectoryUserService>();
//fake account for mock AD call
var adUser = new AdUserAccount {
Email = email,
FirstName = firstname,
LastName = lastname
};
//Need fake ad account to return from async call
activeDirectoryUserMock.Setup(_ => _.GetByNameAsync(name)).ReturnsAsync(adUser);
var mapperMock = new Mock<IMapper>();
var userService = new UserService(userRepositoryMock.Object, activeDirectoryUserMock.Object, mapperMock.Object);
//Act
await userService.RegisterAsync(name, email, firstname, lastname, "password");
//Assert
userRepositoryMock.Verify(x => x.AddAsync(It.IsAny<User>()), Times.Once);
}
关于c# - Unity 和 NUnit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44763233/