单元测试结果中出现NullReferenceException

本文关键字:NullReferenceException 测试结果 单元 | 更新日期: 2023-09-27 18:22:19

我刚刚开始用C#Webforms编程(以前有VB Webforms的经验),我正在开发一个web应用程序,它将成为一个更大项目的一小部分。

我已经创建了3个独立的项目,一个用于web表单,一个为类库,一个则用于测试。

我已经将所有项目添加到一个解决方案中,并添加了适当的引用,Webforms和Tests项目都引用了类库。

我在类库中有一个类,它可以找到登录用户的用户名:

public class LoggedInUser
{
    public string UserName 
    {
        get { return HttpContext.Current.User.Identity.Name; } 
    }
}

在我的一个页面的页面加载事件中,我使用这个类来设置文字的text属性,以在屏幕上显示名称。

    protected void Page_Load(object sender, EventArgs e)
    {
        LoggedInUser CurrentUser = new LoggedInUser();
        LitUser.Text = string.Format(" {0}", CurrentUser.UserName);
    }

这很好用。

为了完成,我想我应该写一个单元测试,以确保登录的用户名是我所期望的。

    [TestMethod]
    public void Test_Logged_In_User_Name()
    {
        LoggedInUser actualUser = new LoggedInUser();
        string expectedUserName = "myUserName";
        string actualUserName = actualUser.UserName;
        Assert.AreEqual(expectedUserName, actualUserName);
    }

当我运行测试时,它抛出以下异常:

System.NullReferenceException: Object reference not set to an instance of an object

在这条线上:

get { return HttpContext.Current.User.Identity.Name; }

任何想法都将一如既往地受到极大的赞赏。

单元测试结果中出现NullReferenceException

您需要为HttpContext创建一个包装器类,该类抽象了您需要的功能。原因是HttpContext只存在于web请求,并且当您从应用程序运行单元测试时,HttpContext将不存在。

此外,任何第三方依赖都应该为其创建一个包装器,以帮助进行测试。

值得注意的是,你根本不应该需要这个测试。在这种情况下,您正在测试第三方代码,这是您所依赖的准确代码。单元测试的目的是测试你自己的代码/逻辑,如果你为每一个第三方方法编写测试,你就永远不会发布产品:)。

至于创建包装类,它们与普通类没有什么不同。您需要为HttpContext类创建一个接口,然后创建一个类似以下内容的包装器:

public class HttpContextWrapper
{
    private readonly IHttpContext _httpContext;
    public HttpContextWrapper()
    {
        _httpContext = HttpContext.Current;
    }
    public HttpContextWrapper(IHttpContext injectedContext)
    {
        _httpContext = injectedContext;
    }
    public string GetName()
    {
        _httpContext.Current.User.Identity.Name;
    }
}

然后,您可以注入HttpContext的伪实现来获得您想要的结果。

实际上,您不一定需要包装和模拟HttpContext。在你的测试设置中,你可以做一些类似于以下的事情:

var sb = new StringBuilder();
TextWriter writer = new StringWriter(sb);
HttpContext.Current = new HttpContext(
     new HttpRequest("path", "http://dummy", ""), 
     new HttpResponse(writer)
)
{
    User = new WindowsPrincipal(WindowsIdentity.GetCurrent()) 
};

在这个例子中,我用当前用户的身份分配了一个windows主体,但在您的场景中,您可能想要分配一个特制的主体,例如ClaimsPrincipal或伪实现(或mock)。