如何单元测试这种方法在C#中? [英] How to unit test this method in c#?

查看:131
本文介绍了如何单元测试这种方法在C#中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习的单元测试。如何单元测试使用NUnit和犀牛嘲笑这种方法吗?

 公众的ActionResult PrintCSV(字节[]字节字符串文件名)
{
    var文件=文件(字节,应用程序/ vnd.ms - Excel中);
    VAR CD =新System.Net.Mime.ContentDisposition()
    {
        CreationDate = DateTime.Now,
        文件名=文件名,
        内嵌= FALSE
    };
    Response.AppendHeader(内容处置,cd.ToString());
    返回文件;
}


解决方案

您将需要模拟的HttpContext。下面是一个例子(这是MSTest的,但我想这不会是一个地狱很多痛苦地移植到NUnit的的 - 所有你需要的是重新命名一对夫妇的属性):

  [TestMethod的]
公共无效PrintCSV_Should_Stream_The_Bytes_Argument_For_Download()
{
    //安排
    VAR SUT =新的HomeController();
    变种字节=新字节[] {1,2,3};
    变种文件名=foobar的;
    VAR的HttpContext = MockRepository.GenerateMock< HttpContextBase>();
    VAR响应= MockRepository.GenerateMock< Htt的presponseBase>();
    httpContext.Expect(X => x.Response).Return(响应);
    VAR的RequestContext =新的RequestContext(HttpContext的,新的RouteData());
    sut.ControllerContext =新的ControllerContext(RequestContext的,SUT);    //行为
    VAR实际= sut.PrintCSV(字节,文件名);    //断言
    Assert.IsInstanceOfType(实际的typeof(FileContentResult));
    var文件=(FileContentResult)实际;
    Assert.AreEqual(字节,file.FileContents);
    Assert.AreEqual(应用程序/ vnd.ms-EXCEL,file.ContentType);
    response.AssertWasCalled(
        X => x.AppendHeader(
            精氨酸<串GT; .Is.Equal(内容处置),
            精氨酸<串GT; .Matches(CD = GT; cd.Contains(附件;)及和放大器; cd.Contains(文件名=+文件名))
        )
    );
}

正如你可以看到有一个有点水暖code在这里设置的考验。我个人使用 MvcContrib.TestHelper ,因为它简化了不少这样的管道$ C的$ c和使测试更具可读性。检查了这一点:

  [识别TestClass]
公共类HomeControllerTests:TestControllerBuilder
{
    私人HomeController的SUT;    [TestInitialize]
    公共无效TestInitialize()
    {
        this.sut =新的HomeController();
        this.InitializeController(this.sut);
    }    [测试方法]
    公共无效PrintCSV_Should_Stream_The_Bytes_Argument_For_Download()
    {
        //安排
        变种字节=新字节[] {1,2,3};
        变种文件名=foobar的;        //行为
        VAR实际= sut.PrintCSV(字节,文件名);        //断言
        var文件= actual.AssertResultIs< FileContentResult>();
        Assert.AreEqual(字节,file.FileContents);
        Assert.AreEqual(应用程序/ vnd.ms-EXCEL,file.ContentType);
        this.HttpContext.Response.AssertWasCalled(
            X => x.AppendHeader(
                精氨酸<串GT; .Is.Equal(内容处置),
                精氨酸<串GT; .Matches(CD = GT; cd.Contains(附件;)及和放大器; cd.Contains(文件名=+文件名))
            )
        );
    }
}

现在的测试更加清楚,因为我们可以立即看到初始化阶段,该方法的测试并断言实际调用

注:这一切都这样说我不太看的控制器操作,需要一个字节数组作为参数的点只是流回给客户端。我的意思是,以调用它的客户端需要已经有文件,有什么意义呢?不过,我想这是只是为了演示。在您的实际方法的字节数组作为参数没有通过,但一些外部依赖你的控制器内的行动检索。在这种情况下,你可以嘲笑这种依赖性以及(假设当然,你已经正确的架构层和他们足够弱耦合)。

i am learning unit testing. How to unit test this method using nunit and rhino mock ?

public ActionResult PrintCSV(Byte[] bytes, string fileName)
{
    var file = File(bytes, "application/vnd.ms-excel");
    var cd = new System.Net.Mime.ContentDisposition()
    {
        CreationDate = DateTime.Now,
        FileName = fileName,
        Inline = false
    };
    Response.AppendHeader("Content-Disposition", cd.ToString());
    return file;
}

解决方案

You will need to mock the HttpContext. Here's an example (it's MSTest but I guess it won't be a hell lot of a pain to port to NUnit - all you need is to rename a couple of attributes):

[TestMethod]
public void PrintCSV_Should_Stream_The_Bytes_Argument_For_Download()
{
    // arrange 
    var sut = new HomeController();
    var bytes = new byte[] { 1, 2, 3 };
    var fileName = "foobar";
    var httpContext = MockRepository.GenerateMock<HttpContextBase>();
    var response = MockRepository.GenerateMock<HttpResponseBase>();
    httpContext.Expect(x => x.Response).Return(response);
    var requestContext = new RequestContext(httpContext, new RouteData());
    sut.ControllerContext = new ControllerContext(requestContext, sut);

    // act
    var actual = sut.PrintCSV(bytes, fileName);

    // assert
    Assert.IsInstanceOfType(actual, typeof(FileContentResult));
    var file = (FileContentResult)actual;
    Assert.AreEqual(bytes, file.FileContents);
    Assert.AreEqual("application/vnd.ms-excel", file.ContentType);
    response.AssertWasCalled(
        x => x.AppendHeader(
            Arg<string>.Is.Equal("Content-Disposition"),
            Arg<string>.Matches(cd => cd.Contains("attachment;") && cd.Contains("filename=" + fileName))
        )
    );
}

As you can see there's a bit of a plumbing code here to setup the test. Personally I use MvcContrib.TestHelper as it simplifies a lot of this plumbing code and makes the test more readable. Check this out:

[TestClass]
public class HomeControllerTests : TestControllerBuilder
{
    private HomeController sut;

    [TestInitialize]
    public void TestInitialize()
    {
        this.sut = new HomeController();
        this.InitializeController(this.sut);
    }

    [TestMethod]
    public void PrintCSV_Should_Stream_The_Bytes_Argument_For_Download()
    {
        // arrange 
        var bytes = new byte[] { 1, 2, 3 };
        var fileName = "foobar";

        // act
        var actual = sut.PrintCSV(bytes, fileName);

        // assert
        var file = actual.AssertResultIs<FileContentResult>();
        Assert.AreEqual(bytes, file.FileContents);
        Assert.AreEqual("application/vnd.ms-excel", file.ContentType);
        this.HttpContext.Response.AssertWasCalled(
            x => x.AppendHeader(
                Arg<string>.Is.Equal("Content-Disposition"),
                Arg<string>.Matches(cd => cd.Contains("attachment;") && cd.Contains("filename=" + fileName))
            )
        );
    }
}

Now the test is much more clear as we can immediately see the initialization phase, the actual invoke of the method under test and the assertion.

Remark: All this being said I don't quite see the point of a controller action that takes a byte array as argument just to stream it back to the client. I mean in order to invoke it the client needs to already have the file, so what's the point? But I guess that was just for illustration purposes. In your actual method the byte array is not passed as argument but is retrieved inside your controller action from some external dependency. In this case you could mock this dependency as well (assuming of course you have properly architected your layers and they are sufficiently weakly coupled).

这篇关于如何单元测试这种方法在C#中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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