gpt4 book ai didi

c# - 使用 UnitOfWork 模拟上下文和存储库

转载 作者:太空宇宙 更新时间:2023-11-03 23:07:45 24 4
gpt4 key购买 nike

我正在为我们需要构建的小型应用构建单元测试。

我已经实现了存储库/工作单元模式。我的经理类实现了工作单元模式。

对于给定的接口(interface):

public interface IUserManager
{
List<ApplicationUser> GetUsers(Expression<Func<ApplicationUser, bool>> filter = null);
ApplicationUser GetUser(Expression<Func<ApplicationUser, bool>> filter);
ApplicationUser AddUser(string username, List<string> environmentIds, bool isAdmin = false);
void DeleteUser(string username);
ApplicationUser UpdateUser(string id, List<string> environmentIds, bool isAdmin = false);
IList<string> GetUserRoles(string id);
}

我已经实现了

public class UserManager : IUserManager
{

#region private fields

private readonly IRepository<ApplicationUser> _userRepository;
private readonly IRepository<Application> _applicationRepository;
private readonly IRepository<Role> _roleRepository;
private readonly IActiveDirectoryManager _activeDirectoryManager;


#endregion

#region ctor

public UserManager(AppDbContext context, IActiveDirectoryManager activeDirectoryManager)

{
_activeDirectoryManager = activeDirectoryManager;
_userRepository = new Repository<ApplicationUser>(context);
_applicationRepository = new Repository<Application>(context);
_roleRepository = new Repository<Role>(context);
}

#endregion


#region IUserManager

public ApplicationUser AddUser(string username, List<string> applicationIds, bool isAdmin = false)
{
//Get the environments in the list of environmentIds
var applications = _applicationRepository.Get(e => applicationIds.Contains(e.Id)).ToList();

//Get the user from AD
var user = _activeDirectoryManager.GetUser(username);

//set the Id
user.Id = Guid.NewGuid().ToString();

//add the environments to the user
applications.ForEach(x =>
{
user.Applications.Add(x);
});

//if the user is an admin - retrieve the role and add it to the user
if (isAdmin)
{
var role = _roleRepository.Get(r => r.Name == "admin").FirstOrDefault();
if (role != null)
{
user.Roles.Add(role);
}
}

//insert and save
_userRepository.Insert(user);
_userRepository.Save();

//return the user
return user;

}

//removed for brevity
}

我的单元测试类:

[TestClass]
public class UserManagerUnitTest
{
private readonly Mock<IActiveDirectoryManager> _adManager;
private readonly IUserManager _userManager;
private readonly Mock<IRepository<Application>> _applicationRepository;
private readonly Mock<IRepository<ApplicationUser>> _userRepository;
private readonly Mock<IRepository<Role>> _roleRepository;


public UserManagerUnitTest()
{
var context = new Mock<AppDbContext>();
_adManager = new Mock<IActiveDirectoryManager>();

_applicationRepository = new Mock<IRepository<Application>>();
_userRepository = new Mock<IRepository<ApplicationUser>>();
_roleRepository = new Mock<IRepository<Role>>();

_userManager = new UserManager(context.Object, _adManager.Object);

}

[TestMethod]
[TestCategory("AddUser"), TestCategory("Unit")]
public void AddUser_ValidNonAdmin_UserIsAdded()
{
#region Arrange

string username = "testUser";
List<string> applicationIds = new List<string>() {"1", "2", "3"};

_applicationRepository.Setup(x => x.Get(It.IsAny<Expression<Func<Application, bool>>>(),
It.IsAny<Func<IQueryable<Application>, IOrderedQueryable<Application>>>(), It.IsAny<string>()))
.Returns(new List<Application>());

_adManager.Setup(x => x.GetUser(It.IsAny<string>())).Returns(new ApplicationUser());


#endregion

#region Act

var result = _userManager.AddUser(username, applicationIds, false);

#endregion

#region Assert
Assert.IsNotNull(result);
Assert.IsFalse(result.IsAdmin);
#endregion
}

}

最后是存储库界面:

    public interface IRepository<TEntity> where TEntity : class
{
IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity> , IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "");

TEntity GetById(object id);
void Insert(TEntity entity);
void Delete(object id);
void Delete(TEntity entityToDelete);
void Update(TEntity entityToUpdate);
void Save();

}

和实现:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class 
{
private readonly AppDbContext _context;
internal DbSet<TEntity> DbSet;

public Repository(AppDbContext context)
{
_context = context;
DbSet = _context.Set<TEntity>();
}

public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = DbSet;

if (filter != null)
query = query.Where(filter);

foreach (var prop in includeProperties.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(prop);
}

if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}


}

public virtual TEntity GetById(object id)
{
return DbSet.Find(id);
}

public virtual void Insert(TEntity entity)
{
DbSet.Add(entity);
}

public virtual void Delete(object id)
{
TEntity entityToDelete = DbSet.Find(id);
Delete(entityToDelete);
}

public void Get(Expression<Func<Application, bool>> expression, Func<IQueryable<Application>> func, IOrderedQueryable<Application> orderedQueryable)
{
throw new NotImplementedException();
}

public virtual void Delete(TEntity entityToDelete)
{
if (_context.Entry(entityToDelete).State == EntityState.Detached)
{
DbSet.Attach(entityToDelete);
}
DbSet.Remove(entityToDelete);
}

public virtual void Update(TEntity entityToUpdate)
{
DbSet.Attach(entityToUpdate);
_context.Entry(entityToUpdate).State = EntityState.Modified;
}

public void Save()
{
_context.SaveChanges();
}
}

我的问题在模拟 IRepository<Application>

            _applicationRepository.Setup(x => x.Get(It.IsAny<Expression<Func<Application, bool>>>(), 
It.IsAny<Func<IQueryable<Application>, IOrderedQueryable<Application>>>(), It.IsAny<string>()))
.Returns(new List<Application>());

出于某种原因 - 正在使用实际方法而不是 Moq 的覆盖代理。当测试执行时——我在存储库的 Get 方法上得到一个空引用——特别是在查询 = DbSet:

 public Repository(AppDbContext context)
{
_context = context;
DbSet = _context.Set<TEntity>();
}

public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
{
IQueryable<TEntity> query = DbSet; **//null here because db should be** mocked

if (filter != null)
query = query.Where(filter);

我正在尝试仅测试 UserManager 实现 - 而不是存储库实现。

设置此测试的正确方法是什么?

最佳答案

问题是您在 UserManager 的构造函数中传递了 AppDbContext,这使得它依赖于它。该类依次创建存储库的内部实例,因此始终使用具体类:

public UserManager(AppDbContext context, IActiveDirectoryManager activeDirectoryManager)
{
_activeDirectoryManager = activeDirectoryManager;
_userRepository = new Repository<ApplicationUser>(context);
_applicationRepository = new Repository<Application>(context);
_roleRepository = new Repository<Role>(context);
}

您应该改为抽象存储库的创建并修改构造函数,以便它采用基于接口(interface)的实例:

public UserManager(IRepository<ApplicationUser> userRepository, IRepository<Application> applicationRepository, IRepository<Role> roleRepository, IActiveDirectoryManager activeDirectoryManager)
{
_activeDirectoryManager = activeDirectoryManager;
_userRepository = userRepository;
_applicationRepository = applicationRepository;
_roleRepository = roleRepository;
}

这样您就可以抽象出存储库,以便使用您的模拟而不是真正的类。

关于c# - 使用 UnitOfWork 模拟上下文和存储库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40598379/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com