C# 单元测试Asp.NETWebAPI:如何使用[FromUri]参数测试方法的正确路由

C# 单元测试Asp.NETWebAPI:如何使用[FromUri]参数测试方法的正确路由,c#,asp.net,unit-testing,asp.net-web-api,C#,Asp.net,Unit Testing,Asp.net Web Api,我想测试这个控制器: [HttpGet] public IList<Notification> GetNotificationsByCustomerAndId([FromUri] string[] name, [FromUri] int[] lastNotificationID) { return _storage.GetNotifications(name, lastNotificationID, _topX); } 当您传递数组时,还有其他方法进行单元

我想测试这个控制器:

[HttpGet]
public IList<Notification> GetNotificationsByCustomerAndId([FromUri] string[] name, [FromUri] int[] lastNotificationID)         
{
    return _storage.GetNotifications(name, lastNotificationID, _topX);
}
当您传递数组时,还有其他方法进行单元测试吗?

也许您可以使用列表而不是字符串[],如中所示

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

编辑 在深入研究这个问题之后,我想知道在GeTruttDebug调用期间是否没有完成非简单类型的模型绑定——毕竟,路由不考虑这些类型,并且不能创建两个不同的路由,例如通过数组中的元素数量。 因此,您应该研究模型绑定,而不是请求路由。
要在不实际执行调用的情况下测试代码,可以手动检索ModelBinder对象并使用该对象解析URL

我认为您应该创建一个新方法,该方法将自动确定数组元素的数量并将它们公开给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);

您可以为数组项创建查询字符串参数列表,然后使用string.join方法和分隔符(&as)将它们连接起来。这将很容易获得所需的查询字符串

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

我相信没有单元测试的方法,相反,您可以为您的方法/对内存中的HttpServer进行集成测试。这看起来像是使用带有查询参数/POST有效负载的http客户端调用您的方法,并将来自服务器的结果与您期望的结果进行比较。根据.NET的要求,数组需要不带括号或带索引括号-?name=first&name=last或name[0]=first&name[1]=last对应于操作参数字符串[]name,但我以前对此感到困惑。我想PHP更喜欢?name[]=first&name[]=last。@Martin我重构了代码,用您的解决方案对其进行了测试,但它不起作用。问题是相同的:routeData。值不包含任何参数信息。是否尝试设置断点,然后从浏览器执行请求?这可能是因为GetRouteData中存在问题。@MartinWiboe我已经从功能级别对其进行了测试。它起作用了。我想做的是用一个单元来测试它test@FrancescoB. 我懂了。我用不同的方法更新了我的答案。如果你尝试一下,我想听听它是否适合你。
[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);
        }