Тестирование модулей 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
, я вижу только controller
и action
.
[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);
}
Есть ли другой способ unit test, когда вы передаете массивы?
Ответы
Ответ 1
Возможно, вы можете использовать List<string>
, а не string[]
, как в этом ответе?
Кроме того, вам может потребоваться поместить name[]
вместо name
в строку запроса.
Edit
Изучив это, я задаюсь вопросом, не выполняется ли привязка модели к непростым типам во время вызова GetRouteData
- в конце концов, маршрутизация не учитывает эти типы, и вы не можете создать два маршрута, которые отличаются, например. количество элементов в переданном массиве.
Итак, вы должны изучить привязку модели вместо маршрутизации запроса.
Чтобы протестировать ваш код без фактического выполнения вызова, вы можете вручную загрузить объект ModelBinder
и использовать его для анализа URL. Этот тест из исходного кода ASP.NET может иметь для вас значение.
Ответ 2
Я думаю, что вы должны создать новый метод, который автоматически определит количество элементов массива и выведет их на 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);
Ответ 3
Вы можете создать список параметров строки запроса для элементов массива, а затем присоединиться к ним с помощью метода 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);
}