单元测试使用Windows身份验证控制器 [英] Unit Testing a controller that uses windows authentication

查看:149
本文介绍了单元测试使用Windows身份验证控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

------- 请参见下面的,因为我现在有这个设置了依赖注入和使用最小起订量嘲讽框架的更新。我还是想分裂我的仓库,所以它并不直接依赖于同一个函数内拉windowsUser。

我在填充下拉一个内部网站一个Web API。下拉背后的查询需要的Windows用户名作为参数,返回列表中。

I have a Web API in an intranet site that populates a dropdown. The query behind the dropdown takes the windows username as a parameter to return the list.

我意识到我没有这一切设置正确,因为我无法单元测试。我需要知道如何应该被设置成允许单元测试,然后将单元测试应该是什么样子。

I realize I don't have all of this set up correctly because I'm not able to unit test it. I need to know how this "should" be set up to allow unit testing and then what the unit tests should look like.

附加信息:这是一个ASP.NET MVC应用5

Additional info: this is an ASP.NET MVC 5 application.

接口

public interface ITestRepository
{
    HttpResponseMessage DropDownList();
}

REPOSITORY

public class ExampleRepository : IExampleRepository
{
    //Accessing the data through Entity Framework
    private MyDatabaseEntities db = new MyDatabaseEntities();

    public HttpResponseMessage DropDownList()
    {
        //Get the current windows user
        string windowsUser =  HttpContext.Current.User.Identity.Name;

        //Pass the parameter to a procedure running a select query
        var sourceQuery = (from p in db.spDropDownList(windowsUser)
                           select p).ToList();

        string result = JsonConvert.SerializeObject(sourceQuery);
        var response = new HttpResponseMessage();
        response.Content = new StringContent(result, System.Text.Encoding.Unicode, "application/json");

        return response;            
    }
}

控制器

public class ExampleController : ApiController
{
    private IExampleRepository _exampleRepository;

    public ExampleController()
    {
        _exampleRepository = new ExampleRepository();
    }

    [HttpGet]
    public HttpResponseMessage DropDownList()
    {
        try
        {
            return _exampleRepository.DropDownList();
        }
        catch
        {
            throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
        }
    }
}

更新1

我已经根据BartoszKP的建议,表明依赖注入更新了我的控制器。

I have updated my Controller based on BartoszKP's suggestion to show dependency injection.

已更新控制器

public class ExampleController : ApiController
{
    private IExampleRepository _exampleRepository;

    //Dependency Injection
    public ExampleController(IExampleRepository exampleRepository)
    {
        _exampleRepository = exampleRepository;
    }

    [HttpGet]
    public HttpResponseMessage DropDownList()
    {
        try
        {
            return _exampleRepository.DropDownList();
        }
        catch
        {
            throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
        }
    }
}

更新2

我决定使用起订量为单元测试嘲弄的框架。我能够测试简单的东西,像下面这样。 这将测试不带任何参数,不包括windowsUser部分的简单方法。

I have decided to use MOQ as a mocking framework for unit testing. I'm able to test something simple, like the following. This would test a simple method that doesn't take any parameters and doesn't include the windowsUser part.

[TestMethod]
public void ExampleOfAnotherTest()
{
    //Arrange
    var mockRepository = new Mock<IExampleRepository>();
    mockRepository
        .Setup(x => x.DropDownList())
        .Returns(new HttpResponseMessage(HttpStatusCode.OK));

    ExampleController controller = new ExampleController(mockRepository.Object);
    controller.Request = new HttpRequestMessage();
    controller.Configuration = new HttpConfiguration();

    //Act            
    var response = controller.DropDownList();

    //Assert
    Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}

我需要帮助测试的DropDownList方法 (一说确实包括code,以获得windowsUser)。我需要如何打散这种方法的建议。我知道这两个部分不应该一直处于同样的方法。我不知道如何安排分裂出来的windowsUser变量。我知道这真的应该作为一个参数被带进来,但我无法弄清楚如何。

I need help testing the DropDownList method (one that does include code to get the windowsUser). I need advice on how to break this method apart. I know both parts shouldn't been in the same method. I don't know how to arrange splitting out the windowsUser variable. I realize this really should be brought in as a parameter, but I can't figure out how.

推荐答案

您平时不单元测试库(集成测试验证他们是否真的正确地坚持在数据库中的数据) - 例如见的这篇文章在MSDN上

You usually do not unit-test repositories (integration tests verify if they really persist the data in the database correctly) - see for example this article on MSDN:

典型地,它是困难的单元测试存储库本身,因此它往往是最好编写集成测试它们。

Typically, it is difficult to unit test the repositories themselves, so it is often better to write integration tests for them.

所以,让我们着重测试仅控制器。

So, let's focus on testing only the controller.

改变控制器取 IExampleRepository 在其构造函数作为参数:

Change the controller to take IExampleRepository in its constructor as a parameter:

private IExampleRepository _exampleRepository;

public ExampleController(IExampleRepository exampleRepository)
{
    _exampleRepository = exampleRepository;
}

然后,在你的单元测试,用嘲讽的框架之一(如 RhinoMock 例如)来创建测试控制器的唯一目的的存根。

Then, in your unit tests, use one of mocking frameworks (such as RhinoMock for example) to create a stub for the sole purpose of testing the controller.

[TestFixture]
public class ExampleTestFixture
{
    private IExampleRepository CreateRepositoryStub(fake data)
    {
        var exampleRepositoryStub = ...; // create the stub with a mocking framework

        // make the stub return given fake data

        return exampleRepositoryStub;
    }

    [Test]
    public void GivenX_WhenDropDownListIsRequested_ReturnsY()
    {
        // Arrange
        var exampleRepositoryStub = CreateRepositoryStub(X);
        var exampleController = new ExampleController(exampleRepositoryStub);

        // Act
        var result = exampleController.DropDownList();

        // Assert
        Assert.That(result, Is.Equal(Y));
    }  
}

这仅仅是一个快速和放大器;脏的例子 - CreateRepositoryStub 方法应该是场提取到一些测试工具类的。也许它应该返回一个流畅的界面,使测试的的安排的部分对什么是给予更多的可读性。更多的东西,如:

This is just a quick&dirty example - CreateRepositoryStub method should be of course extracted to some test utility class. Perhaps it should return a fluent interface to make the test's Arrange section more readable on what is given. Something more like:

// Arrange
var exampleController
    = GivenAController()
      .WithFakeData(X);

(有更好的名称反映,当然你的业务逻辑)。

(with better names that reflect your business logic of course).

在ASP.NET MVC的情况下,框架需要知道如何构建控制器。幸运的是,ASP.NET支持依赖注入模式,不需要参数的构造函数时,<一个href=\"http://www.asp.net/mvc/overview/older-versions/hands-on-labs/aspnet-mvc-4-dependency-injection\"相对=nofollow>使用MVC团结。

In case of ASP.NET MVC, the framework needs to know how to construct the controller. Fortunately, ASP.NET supports the Dependency Injection paradigm and a parameterless constructor is not required when using MVC unity.

此外,注意到理查德·绍洛伊的注释:

您不应该使用的WebAPI HttpContext.Current - 您可以使用 base.User 这是从的Htt prequestBase.User 并mockable。如果你真的想继续使用 HttpContext.Current ,看一看的假装HttpContext.Current测试init方法

You shouldn't use HttpContext.Current in WebApi - you can use base.User which comes from HttpRequestBase.User and is mockable. If you really want to continue using HttpContext.Current, take a look at Mock HttpContext.Current in Test Init Method

这篇关于单元测试使用Windows身份验证控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆