我在自定义UserStore和RoleStore中使用ASP.Identity 这是我的数据库上下文:
public class AppDbContext
: IdentityDbContext<User, Role, int, UserLogin, UserRole, UserClaim>
我在Seed方法中有以下代码来添加用户:
// UserManager
var userStore = new UserStore<User, Role, int, UserLogin, UserRole, UserClaim>(context)
var userManager = new UserManager<User, int>(userStore);
// RoleManager
var roleStore = new RoleStore<Role, int, UserRole>(context)
var roleManager = new RoleManager<Role, int>(roleStore);
// Create Roles
roleManager.Create(new Role(roleName));
...
// Create Users
var user = new User { ... };
var result = userManager.Create(user, password);
...
// Add Users to Roles
userManager.AddToRole(user.Id, roleName);
...
如何使用Mock框架进行单元测试?
我需要为以下方法编写单元测试:
public IEnumerable<User> GetUsersInRole(string roleName)
{
return (from u in this.DbContext.Users
from ur in u.Roles
join r in this.DbContext.Roles on ur.RoleId equals r.Id
where r.Name == roleName
select u).Distinct();
}
这是我测试方法的一部分:
this.Bind<Mock<AppDbContext>>()
.ToMethod(
m =>
NunitTestHelper.GetDbContextMock()
//.SetupDbContextData(x => x.Roles, this.RolesCollection.AsQueryable())
//.SetupDbContextData(x => x.Users, this.UsersCollection.AsQueryable())
).InTransientScope();
var context = this.Kernel.Get<AppDbContext>();
var userStore = new Mock<UserStore<User, Role, int, UserLogin, UserRole, UserClaim>>(context);
var userManager = new UserManager<User, int>(userStore.Object);
var roleStore = new Mock<RoleStore<Role, int, UserRole>>(context);
var roleManager = new RoleManager<Role, int>(roleStore.Object);
roleManager.Create(new Role(roleName));
for (var i = 0; i < num; i++)
{
var id = i + 1;
var user = new User { Id = id, UserName = "User" + i };
var result = userManager.Create(user);
userManager.AddToRole(id, roleName); // Exception
}
在线&#34; userManager.AddToRole&#34;我得到以下异常:
&#34;未找到UserId。&#34;
如何在单元测试中将用户添加到角色?
我无法直接访问UserRoles实体。
答案 0 :(得分:1)
我尝试使用不同的框架和方法多次模拟DbContext
。从来没有我能得到一个可靠的模拟对象,在所有情况下表现得像真实的一样。
或者当我可以模拟DbContext
时,设置代码非常庞大且难以设置,这是不值得的。此外,该设置非常脆弱,并且在实际代码的每次更改时都会出现问题。
测试与数据库相关的代码的最佳方法是转到实际的数据库。这些测试不再是单元测试,而是成为集成测试。但这是一个术语 - 您仍在测试代码(和数据库结构)。
不幸的是,设置可靠运行的数据库测试需要花费更多的精力。但是如果你想看看这个,这里有一些参考:
答案 1 :(得分:0)
谢谢!我找到了解决方案,但我不确定这是否是一个好方法。
所以,我已经实现了我的测试用户:
public class TestUser : User
{
private List<UserRole> roles;
public TestUser()
{
this.roles = new List<UserRole>();
}
public override ICollection<UserRole> Roles
{
get
{
return this.roles;
}
}
public TestUser AddRole(Role role)
{
this.roles.Add(new UserRole { RoleId = role.Id, UserId = this.Id });
return this;
}
}
在我的单元测试设置中:
// Private Members
private List<Role> rolesCollection;
private List<TestUser> usersCollection;
// Public Properties
public IList<Role> RolesCollection
{
get
{
return this.rolesCollection ?? (this.rolesCollection = new List<Role>(NunitTestDataHelper.GetRoles()));
}
}
public IList<TestUser> UsersCollection
{
get
{
return this.usersCollection
?? (this.usersCollection =
new List<TestUser>(
new[]
{
new TestUser { Id = 1, UserName = "Usr1" }.AddRole(this.RolesCollection[0]).AddRole(this.rolesCollection[1]),
new TestUser { Id = 2, UserName = "Usr2" }.AddRole(this.RolesCollection[0]),
new TestUser { Id = 3, UserName = "User1" }.AddRole(this.rolesCollection[1]),
new TestUser { Id = 4, UserName = "User2" },
...
}));
}
}
// Setup DB
this.Bind<Mock<AppDbContext>>()
.ToMethod(
m =>
NunitTestHelper.GetDbContextMock()
.SetupDbContextData(x => x.Roles, this.RolesCollection.AsQueryable())
.SetupDbContextData(x => x.Users, this.UsersCollection.AsQueryable()))
.InTransientScope();
我的单元测试运行良好!