Asp.net mvc 4 MVC4单元测试和windows身份验证

Asp.net mvc 4 MVC4单元测试和windows身份验证,asp.net-mvc-4,windows-authentication,vs-unit-testing-framework,Asp.net Mvc 4,Windows Authentication,Vs Unit Testing Framework,在我看来,除非当我从TestMethod创建控制器实例时,我的mvc4应用程序使用windows身份验证(因此我的控制器尝试读取用户对象),否则用户对象将保持空。所以我的测试失败了。我能做些什么让他们工作 其他信息: 这是我的测试: [TestMethod] public void Create() { var ctrl = new LanguageController(); var res = ctrl.Manage() as ViewResult; Assert.IsNot

在我看来,除非当我从TestMethod创建控制器实例时,我的mvc4应用程序使用windows身份验证(因此我的控制器尝试读取用户对象),否则用户对象将保持空。所以我的测试失败了。我能做些什么让他们工作

其他信息: 这是我的测试:

[TestMethod]
public void Create()
{
   var ctrl = new LanguageController();
   var res = ctrl.Manage() as ViewResult;
   Assert.IsNotNull(res);
   Assert.AreEqual(res.ViewName, "Create");
}
我的LanguageController有一个基类:

public class LanguageController : MyController
{
它有一个构造函数,在它里面我试图通过一个外部权限管理器来发现用户权限

public class MyController : Controller
  {
     protected Rights rm;
     public MyController()
     {
        this.rm = RightManager.Discover(User.Identity);
     }

在这个构造器中,我看到用户为null。

好的,单元测试中存在一些问题,我将在解释用户为null的原因时讨论这些问题

这只是因为您没有提供用户(IPrincipal)实例的存根版本。因此,您需要找到一种方法将其注入控制器。重要的是,您在控制器中外部化了尽可能多的依赖项,因此它不仅提供了一个干净的控制器来使用,而且重要的是,它还提升了性能

我要做的是注入依赖项,如下所示

您的SUT(测试中的系统)

这使我能够注入一个假用户和一个假权限管理器

public class MyController : Controller
  {
     protected Rights rm;
     public MyController()
     {
        this.rm = RightManager.Discover(User.Identity);
     }
那么,当您在运行时运行应用程序时,如何获得真正的用户RightManager呢

您可以在控制器创建期间执行此操作

如果您不使用框架(理想情况下应该使用),您仍然可以手动注入依赖项。例如,在控制器中创建属性并在控制器中注入真实实例,以及在单元测试期间注入假实例等。我将不详细介绍,因为我有点偏离-但是您可以找到很多关于这方面的问题/web参考

您的单元测试 现在您有了一种注入依赖项的方法,您可以轻松地从单元测试中注入依赖项。您可以使用一个(AKA和Mock对象框架),也可以使用老式的方式注入它们,即手写Mock/fakes/stubs。我建议使用隔离框架。创建人工伪造,引入不必要的代码复制和维护问题。因为我不知道您喜欢哪种框架,所以我创建了一些手写的赝品/仿制品/存根

public class FakeRightManager : IRightManager {
    public Rights Discover(IIdentity identity) {
        return new Rights();
    }
}

public class MyFakeIdentity : IIdentity {
    public string AuthenticationType {
        get { throw new NotImplementedException(); }
    }

    public bool IsAuthenticated {
        get { throw new NotImplementedException(); }
    }

    public string Name {
        get { throw new NotImplementedException(); }
    }
}

public class MyFakePrincipal : IPrincipal {
    public IIdentity Identity {
        get { return new MyFakeIdentity(); }
    }

    public bool IsInRole(string role) {
        throw new NotImplementedException();
    }
}
您可以使用单元测试:

    [TestMethod]
    public void ManageAction_Execute_ReturnsViewNameManager()
    {
        var fakeUser = new MyFakePrincipal();
        var fakeRightManager = new FakeRightManager();
        var ctrl = new LanguageController(fakeUser, fakeRightManager);

        var res = ctrl.Manage() as ViewResult;

        Assert.AreEqual<string>(res.ViewName, "Manage");
    } 
[TestMethod]
public void ManageAction\u Execute\u returns查看名称管理器()
{
var fakeUser=new MyFakePrincipal();
var fakeRightManager=新的fakeRightManager();
var ctrl=新语言控制器(fakeUser、fakeRightManager);
var res=ctrl.Manage()作为ViewResult;
Assert.AreEqual(res.ViewName,“Manage”);
} 
在测试中,检查Assert.IsNotNull(res);这是不必要的,因为如果res为null,那么您的第二个断言无论如何都会失败


此外,请始终提供一个非常具有描述性的精确单元测试名称。准确反映您测试的内容。它提高了测试的可读性和可维护性。

您能更具体一点吗?例如,到目前为止您尝试了什么?你的测试代码和被测试的代码是什么样子的?这有助于你得到快速准确的答案。我将这些信息添加到了我的原始问题中。