C# 如何编写模拟不同用户的测试?
My Winforms应用程序根据当前进程中找到的组成员身份设置权限 我刚刚在MSTEST中做了一个单元测试 我想以其他用户的身份运行它,以便验证预期的行为 以下是我的拍摄目的:C# 如何编写模拟不同用户的测试?,c#,winforms,mstest,impersonation,C#,Winforms,Mstest,Impersonation,My Winforms应用程序根据当前进程中找到的组成员身份设置权限 我刚刚在MSTEST中做了一个单元测试 我想以其他用户的身份运行它,以便验证预期的行为 以下是我的拍摄目的: [TestMethod] public void SecuritySummaryTest1() { Impersonate(@"SomeDomain\AdminUser", password); var target = new DirectAgentsSecur
[TestMethod]
public void SecuritySummaryTest1()
{
Impersonate(@"SomeDomain\AdminUser", password);
var target = new DirectAgentsSecurityManager();
string actual = target.SecuritySummary;
Assert.AreEqual(
@"Default=[no]AccountManagement=[no]MediaBuying=[no]AdSales=[no]Accounting=[no]Admin=[YES]", actual);
}
[TestMethod]
public void SecuritySummaryTest2()
{
Impersonate(@"SomeDomain\AccountantUser", password);
var target = new DirectAgentsSecurityManager();
string actual = target.SecuritySummary;
Assert.AreEqual(
@"Default=[no]AccountManagement=[YES]MediaBuying=[no]AdSales=[no]Accounting=[YES]Admin=[NO]", actual);
}
我没有包括ImpersonationException的实现,但这并不重要。它没有任何特殊功能。您应该使用模拟对象来模拟处于不同状态的依赖对象。 有关模拟框架的示例,请参见:
您需要抽象出界面后面提供当前用户的位。并将该接口的模拟传递给被测试的类。如果满足您的用例,您还可以直接设置当前主体:
System.Threading.Thread.CurrentPrincipal
= new WindowsPrincipal(new WindowsIdentity("testuser@contoso.com"));
根据本标准,在每次试验方法后,恢复主体。
请注意,如果与检查主体的web服务客户端一起使用,此方法将不起作用(对于本用例,Jim Bolla的解决方案工作得很好) 另一件要添加到Markus解决方案中的事情是,您可能还需要将HttpContext.Current.User设置为您正在为角色管理器的某些调用创建/模拟的Thread.CurrentPrincipal(例如:Roles.GetRolesForUser(Identity.Name))如果您使用该方法的无参数版本,则不需要这样做,但我有一个授权基础结构,需要传递用户名 使用模拟线程调用该方法签名。CurrentPrincipal将失败,原因是“仅当用户名参数与当前Windows标识中的用户名匹配时,才支持该方法”。如消息所示,WindowsTokenRoleProvider代码中存在针对“HttpContext.Current.Identity.Name”。如果它们不匹配,该方法将失败 下面是一个ApiController的示例代码,演示了一个操作的授权。我使用模拟进行单元和集成测试,这样我就可以在不同的AD角色下进行QA,以确保在部署之前安全工作正常
using System.Web
List<string> WhoIsAuthorized = new List<string>() {"ADGroup", "AdUser", "etc"};
public class MyController : ApiController {
public MyController() {
#if TEST
var myPrincipal = new WindowsPrincipal(new WindowsIdentity("testuser@contoso.com"));
System.Threading.Thread.CurrentPrincipal = myPrincipal;
HttpContext.Current.User = myPrincipal;
#endif
}
public HttpResponseMessage MyAction() {
var userRoles = Roles.GetRolesForUser(User.Identity.Name);
bool isAuthorized = userRoles.Any(role => WhoIsAuthorized.Contains(role));
}
}
使用System.Web
List WHOISUTHORIZED=新列表(){“ADGroup”、“AdUser”、“etc”};
公共类MyController:ApiController{
公共MyController(){
#如果测试
var myPrincipal=新的WindowsPrincipal(新的WindowsIdentity(“testuser@contoso.com"));
System.Threading.Thread.CurrentPrincipal=myPrincipal;
HttpContext.Current.User=myPrincipal;
#恩迪夫
}
公共HttpResponseMessage MyAction(){
var userRoles=Roles.GetRolesForUser(User.Identity.Name);
bool isAuthorized=userRoles.Any(role=>whoiauthorized.Contains(role));
}
}
希望这对其他人有帮助:)使用
运行Install Package SimpleImpersonation
安装nuget软件包
然后
var credentials = new UserCredentials(domain, username, password);
Impersonation.RunAsUser(credentials, LogonType.NewCredentials, () =>
{
// Body of the unit test case.
});
这是最简单、最优雅的解决方案。即使我只测试一个类的属性?是不是存在对o/s安全子系统的依赖性,该子系统会覆盖?@LasseV.Karlsen。你能解释一下为什么模拟用户不会使其成为单元测试吗?如果我有一个方法,当用户这样做时,该方法会失败吗没有权限,我想对该场景进行单元测试,以实现代码覆盖率。您依赖于周围的环境,例如用户在域/服务器上,用户仍然处于活动状态,密码仍然正确等。相反,模拟检索权限的部分,以便测试中的代码可以通过不必模拟用户。任何依赖于正确设置的环境(即代码之外的内容)的测试都是集成创建测试,而不是单元测试。
var credentials = new UserCredentials(domain, username, password);
Impersonation.RunAsUser(credentials, LogonType.NewCredentials, () =>
{
// Body of the unit test case.
});