如何将测试单元代码分解为可重复使用的'码?

时间:2016-01-23 04:16:08

标签: c# unit-testing methods mocking httpcontext

我在一些测试方法中嘲笑HTTPContext。我有很多需要编写的方法,所以我宁愿重复使用代码而不是每次都写代码。保持干燥。

我正在实施this method of Faking (Mocking) HTTPContext。我读到我需要将其分解为工厂,以便在其他单元测试中重复使用它。

问题:如何将此代码放入工厂以在单元测试中重复使用?还有一种更好的方法吗?工厂'重用这个?我该如何实现呢。

测试代码

public class MyController : Controller
{

    [HttpPost]
    public void Index()
    {
        Response.Write("This is fiddly");
        Response.Flush();
    }
}

//Unit Test

[Fact]

public void Should_contain_fiddly_in_response()
{

    var sb = new StringBuilder();

    var formCollection = new NameValueCollection();
    formCollection.Add("MyPostedData", "Boo");

    var request = A.Fake<HttpRequestBase>();
    A.CallTo(() => request.HttpMethod).Returns("POST");
    A.CallTo(() => request.Headers).Returns(new NameValueCollection());
    A.CallTo(() => request.Form).Returns(formCollection);
    A.CallTo(() => request.QueryString).Returns(new NameValueCollection());

    var response = A.Fake<HttpResponseBase>();
    A.CallTo(() => response.Write(A<string>.Ignored)).Invokes((string x) => sb.Append(x));

    var mockHttpContext = A.Fake<HttpContextBase>();
    A.CallTo(() => mockHttpContext.Request).Returns(request);
    A.CallTo(() => mockHttpContext.Response).Returns(response);

    var controllerContext = new ControllerContext(mockHttpContext, new RouteData(), A.Fake<ControllerBase>());

    var myController = GetController();
    myController.ControllerContext = controllerContext;


    myController.Index();

    Assert.Contains("fiddly", sb.ToString());
}

1 个答案:

答案 0 :(得分:1)

这取决于您的需求 也许它足以创建一个可以创建伪上下文实例的类。也许有一些方法可以让你创建充满不同数据的上下文。

public class FakeContextFactory
{
     public ControllerContext Create() {/*your mocking code*/}

     public ControllerContext Create(NameValueCollection formVariables) {...}

     ...
}

public void Test()
{
    var context = new FakeContextFactory().Create();
    ...
}

在某些情况下,它可能是一个静态工厂,由具有静态方法的类表示。

如果您需要很多不同的上下文,那么使用构建器模式可能会更好。

public void Test()
{
    var context = FakeContextBuilder.New()
                      .SetRequestMethod("POST")
                      .Build();
    ...
}