我想实际测试一次我的代码,但模拟一直是我的致命弱点之一。
我正在用AD做一些事情,想在不实际接触它的情况下进行测试。这就是我正在做的事情。
var userPrincipalMock = new Mock<UserPrincipal>();
userPrincipalMock.Setup(x => x.SamAccountName).Returns("somesamaccountname");
userPrincipalMock.Setup(x => x.EmployeeId).Returns("anemployeenumber");
但是... 显然 UserPrincipal不想轻易放弃对一个同名账户的控制。
Message "Unsupported expression: x => x.SamAccountName\nNon-overridable members (here: Principal.get_SamAccountName) may not be used in setup / verification expressions."
你们这些可爱的家伙或姑娘们有谁知道正确的方法吗?
不可能测试那些没有被标记为... virtual
. 由于这个原因,应该只对接口进行嘲讽。为了解决你的问题,你可以创建一个包装器。
interface IUserPrincipalWrapper
{
string SamAccountName { get; set; }
string EmployeeId { get; set; }
void Delete();
... // Add all methods and properties of UserPrincipal that you need
}
class UserPrincipalWrapper : IUserPrincipalWrapper
{
private UserPrincipal Implementation { get; }
UserPrincipalWrapper(UserPrincipal implementation)
{
Implementation = implementation;
}
public string SamAccountName
{
get => Implementation.SamAccountName;
set => Implementation.SamAccountName = value;
}
public string EmployeeId
{
get => Implementation.EmployeeId;
set => Implementation.EmployeeId = value;
}
public void Delete()
{
Implementation.Delete();
}
...
// Call or set everything to Implementation...
// This is needed to create an interface around UserPrincipal, which you can mock
}
// Factory is needed for mocking `new` calls..
// as often times, you don't want to test that either
interface IUserPrincipalFactory
{
IUserPrincipalWrapper Create(PrincipalContext context);
}
class UserPrincipalFactory : IUserPrincipalFactory
{
public IUserPrincipalWrapper Create(PrincipalContext context)
{
var implementation = new UserPrincipal(context);
return new UserPrincipalWrapper(implementation);
}
}
然后在你的测试中,你可以模拟所有的东西。
// This is your mock
var userPrincipalMock = new Mock<IUserPrincipalWrapper>();
// You need factory for mocking `new UserPrincipal();` calls
var factoryMock = new Mock<IUserPrincipalWrapperFactory>();
factoryMock.Setup(factory => factory.Create(It.IsAny<PrincipalContext>())).Returns(userPrincipalMock.Object);
// Now it works :)
userPrincipalMock.Setup(x => x.SamAccountName).Returns("somesamaccountname");
userPrincipalMock.Setup(x => x.EmployeeId).Returns("anemployeenumber");