2015-12-02 48 views
17

我想测试该控制器:单元测试Asp.Net的WebAPI:如何测试与[FromUri]的方法的正确路由参数

[HttpGet] 
public IList<Notification> GetNotificationsByCustomerAndId([FromUri] string[] name, [FromUri] int[] lastNotificationID)   
{ 
    return _storage.GetNotifications(name, lastNotificationID, _topX); 
} 

特别地,在该方法我想测试数组传入输入以形成请求Url,是进入routeData.Values的相同数组。如果是单值参数(不是数组),它可以工作,但不适用于数组。如果我调试Values我只看到controlleraction

[TestMethod] 
public void GetNotificationsByCustomerAndId_ArrayOverload_Should_Match_InputParameter_name() 
{ 
    string[] _testName = new string[] { _testCustomer, _testCustomerBis }; 

    string Url = string.Format(
      "http://www.testpincopallo.it/Notifications/GetByCustomerAndLastID/customersNotificationsInfos?name={0}&name={1}&lastNotificationID={2}&lastNotificationID={3}", 
      _testName[0], _testName[1], 
      _testNotificationID, _testNotificationIDBis); 

    IHttpRouteData routeData = GetRouteData(Url); 
    routeData.Values["name"].Should().Be(_testName); 
} 

在传递数组时,还有另一种单元测试的方法吗?

+1

我相信有没有办法“单元”测试它,而不是你可以做你的方法/内存HttpServer集成测试。它看起来像使用http客户端使用查询参数/ POST Payload调用您的方法,并将来自服务器的结果与您期望的结果进行比较。 –

回答

3

也许你可以使用List<string>而不是string[]this answer

此外,您可能需要在查询字符串中输入name[]而不是name

编辑
寻找到这之后,我想知道是否模型非简单类型的结合GetRouteData通话中未完成的 - 毕竟,路由不考虑这些类型的,你不能创建两条路线不同之处在于例如。传递数组中元素的数量。

所以你应该看看模型绑定,而不是请求路由。 要在没有实际执行调用的情况下测试您的代码,您可以手动检索ModelBinder对象并使用它来解析URL。 This test from the ASP.NET source code might be relevant for you.

+1

根据http://stackoverflow.com/questions/9508265/how-do-i-accept-an-array-as-an-asp-net-mvc-controller-action-parameter .NET期望数组或者没有括号或带索引的括号 - '?name = first&name = last'或'name [0] = first&name [1] = last'对应于Action参数'string [] name',但我之前一直困惑。只要提一下,我认为PHP更喜欢'?name [] = first&name [] = last'。 – drzaus

+0

@Martin我重构了我的代码以使用您的解决方案进行测试,但它不起作用。问题是相同的:routeData.Values不包含任何参数信息。 –

+0

您是否尝试过设置断点,然后从浏览器执行请求?这可能是由于'GetRouteData'中的问题。 –

1

我认为你应该创建一个新的方法,它会自动确定数组元素的数量并将它们暴露给url。

private static void ParameterSubstitution(string[] testName, string[] testNotification, ref string url) 
{ 
    const string firstParametrName = "name"; 
    const string secondParametrName = "lastNotificationID"; 
    // first parametr 
    url += string.Format("?{0}={1}", firstParametrName, string.Join(string.Format("&{0}=", firstParametrName), testName)); 
    // second parametr 
    url += string.Format("&{0}={1}", secondParametrName, string.Join(string.Format("&{0}=",secondParametrName), testNotification)); 
} 

,然后你可以使用它像:

var testName = new[] { "Name1", "Name2"}; 
var testNotification = new[] { "Notification1", "Notification2", "Notification3" }; 

var Url = 
    @"http://www.testpincopallo.it/Notifications/GetByCustomerAndLastID/customersNotificationsInfos"; 

ParameterSubstitution(testName, testNotification, ref Url); 
1

您可以创建数组项查询字符串参数的列表,然后使用的string.join方法加入他们与&作为分隔符。这应该很容易地为你提供所需的查询字符串。

[TestMethod] 
     public void GetNotificationsByCustomerAndId_ArrayOverload_Should_Match_InputParameter_name() 
     { 
      string[] _testName = new string[] { _testCustomer, _testCustomerBis }; 

      // ASSUMING _testNotificationIDBis IS STRING ARRAY 
      List<string> nParams = _testName.Select(n => string.Format("lastNotificationID={0}", n)).ToList<string>(); 
      string Url = string.Format(
       "http://www.testpincopallo.it/Notifications/GetByCustomerAndLastID/customersNotificationsInfos?name={0}&name={1}&{2}", 
       _testName[0], _testName[1], 
       String.Join("&", nParams.ToArray())); 

      IHttpRouteData routeData = GetRouteData(Url); 
      routeData.Values["name"].Should().Be(_testName); 
     } 
相关问题