2011-03-10 73 views
3

我正在使用ASP.NET MVC 3NUnit。我正在嘗試編寫一個單元來測試我的一個輔助方法。那就是:如何單元測試UrlHelper自定義幫助程序方法

public static class UrlHelperAssetExtensions 
{ 
    private static readonly string yuiBuildPath = "http://yui.yahooapis.com/2.8.2r1/build/"; 

    public static string YuiResetFontsGridsStylesheet(this UrlHelper helper) 
    { 
     return helper.Content(yuiBuildPath + "reset-fonts-grids/reset-fonts-grids.css"); 
    } 
} 

這裏是我的單元測試:

[Test] 
public void YuiResetFontsGridsStylesheet_should_return_stylesheet() 
{ 
    // Arrange 
    RequestContext requestContext = new RequestContext(); 
    UrlHelper urlHelper = new UrlHelper(requestContext); 

    // Act 
    string actual = urlHelper.YuiResetFontsGridsStylesheet(); 

    // Assert 
    string expected = yuiBuildPath + "reset-fonts-grids/reset-fonts-grids.css"; 
    Assert.AreEqual(expected, actual); 
} 

我是不是測試了正確的方法是什麼?當我在NUnit GUI中運行它時,出現以下錯誤:

System.ArgumentNullException:值不能爲空。 參數名稱:httpContext

這可能測試嗎?如果是這樣,請清楚解釋如何獲得httpContext的實例?

修訂

我不能讓這個測試通過。在我的方法,我有以下:

private static readonly string stylesheetPath = "~/Assets/Stylesheets/"; 

public static string Stylesheet(this UrlHelper helper) 
{ 
    return helper.Content(stylesheetPath + "MyStylesheet.css"); 
} 

,我寫它的測試如下:

private string stylesheetPath = "/Assets/Stylesheets/"; 
private HttpContextBase httpContextBaseStub; 
private RequestContext requestContext; 
private UrlHelper urlHelper; 

[SetUp] 
public void SetUp() 
{ 
    httpContextBaseStub = MockRepository.GenerateStub<HttpContextBase>(); 
    requestContext = new RequestContext(httpContextBaseStub, new RouteData()); 
    urlHelper = new UrlHelper(requestContext); 
} 

[Test] 
public void Stylesheet_should_return_stylesheet() 
{ 
    // Act 
    string actual = urlHelper.Stylesheet(); 

    // Assert 
    string expected = stylesheetPath + "MyStylesheet.css"; 
    Assert.AreEqual(expected, actual); 
} 

NUnit的GUI提供了以下錯誤:

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

似乎得到錯誤〜:

private static readonly string stylesheetPath = "~/Assets/Stylesheets/"; 
+0

您的異常調用堆棧可以幫助 – 2011-03-10 14:14:18

回答

8

你需要模擬HttpContext。下面是使用Moq的例子:

// Arrange 
    var context = new Mock<HttpContextBase>(); 
    RequestContext requestContext = new RequestContext(context.Object, new RouteData()); 
    UrlHelper urlHelper = new UrlHelper(requestContext); 

如果你不想用嘲弄的框架,你可以創建一個類,從HttpContextBase獲得並使用它來代替。但是這需要實現大量的抽象成員,你可以通過嘲笑來避免。

+0

感謝。你怎麼知道2個RequestContext參數中的哪一個來模擬?爲什麼只是一個而不是兩個? – 2011-03-10 12:49:54

+0

@Brendan - 你不需要模擬RouteData,你可以創建一個實例。你可能會先用你的路由定義填充它。 – 2011-03-10 13:26:48

+0

請參閱我的更新,以瞭解我遇到的另一個問題。 – 2011-03-10 13:47:33

2

我個人喜歡用MVCContrib TestHelper

// arrange 
// TODO: You could move this part in the SetUp part of your unit test 
// to avoid repeating it in all tests 
var cb = new TestControllerBuilder(); 
cb 
    .HttpContext 
    .Response 
    .Stub(x => x.ApplyAppPathModifier(Arg<string>.Is.Anything)) 
    .WhenCalled(mi => 
    { 
     mi.ReturnValue = mi.Arguments[0]; 
    }) 
    .Return(null); 
var rc = new RequestContext(cb.HttpContext, new RouteData()); 
var helper = new UrlHelper(rc); 

// act 
var actual = helper.Stylesheet(); 

// assert 
Assert.AreEqual("/Assets/Stylesheets/MyStylesheet.css", actual); 
+0

你可以請你解釋一下你在做什麼var cb = new TestControllerBuilder();? – 2011-03-11 05:41:00

+0

@Brendan Vogt,我將'UrlHelper.Content'方法內部使用的'Response.ApplyAppPathModifier'方法存根。我使用'WhenCalled'結構,它允許我提供基於調用參數的返回值。所以在這種情況下,我只需返回用作參數的值。用一個簡單的'.Return'來實現這一點是不可能的,因爲我們不知道這個方法將被調用什麼參數。我同意這個語法有點複雜,但這就是Rhino Mocks所做的。在'Moq' IIRC中,您可以直接指定基於輸入的返回值。 – 2011-03-11 07:12:42

+0

創建像Jakub這樣的存根有什麼問題嗎? – 2011-03-11 12:16:27

相關問題