2013-01-16 31 views
3

我正在学习单元测试。如何使用nunit和rhino mock单元测试这种方法?如何在c#中单元测试这个方法?

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; 
} 
+3

首先你需要决定你想测试什么? – KingCronus

+0

In Assert it should check,expected file = actual file –

+0

因此,您的第一次测试应该可能是结果实际上是一个文件?然后你可以扩展它,并确保标题是正确的。 – KingCronus

回答

5

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

[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)) 
     ) 
    ); 
} 

正如你可以看到有一个这里有一个管道代码来设置测试。我个人使用MvcContrib.TestHelper,因为它简化了很多这种管道代码,使测试更具可读性。检查了这一点:

[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)) 
      ) 
     ); 
    } 
} 

现在的测试更加清晰,我们马上就可以看到初始化阶段,该方法的测试和断言实际调用。

备注:所有这一切都被说成我不太明白控制器操作的重点,它只需要一个字节数组作为参数,然后将其传回客户端。我的意思是,为了调用它,客户端需要已经有文件,那么有什么意义?但我想这只是为了说明的目的。在实际的方法中,字节数组不是作为参数传递的,而是在你的控制器动作中从一些外部依赖关系中获取的。在这种情况下,你也可以嘲笑这种依赖(当然,假设你已经正确地构建了你的图层,并且它们耦合得非常弱)。

+0

谢谢。这是工作。 –

+0

很高兴能帮到你。还有什么你想问的,或者你可能会考虑接受这个答案? –