Как извлечь значения из Де-сериализованного JSONArray в c#?

#c# #.net #specflow #testcase

Вопрос:

У меня есть класс модели в c#, как показано ниже:

 public class Persons {

    public String Name {get; set;}
    public int Age {get; set;}
    public String InsuranceId {get; set;}
}
 

Я десериализую часть ответа API в этом классе.

 {
  "persons": [
    {
      "name": "SteveBruns",
      "age": 24,
      "insuranceId": "M2409891"
    },
    {
      "name": "JohnStash",
      "age": 34,
      "insuranceId": "N2789012"
    }
  ]
}
 

Я должен проверить все поля name и insuranceId в своем проекте SpecFlow. Допустим, у нас есть файл функций следующего вида:

 Feature: To hit a GET endpoint and fetch the person details

@Feature-106
Scenario: Fetch the details and validate insurance Id
Given I have a valid token
When I create a GET request for /api/insuranceDetails
Then I should validate <name1>, <name2>, <insuranceId1> and <insuranceId2> fields

Examples:
|name1      |insuranceId1 |name2     |insuranceId2|
|SteveBruns |M2409891     |JohnStash |N2789012    |
 

Это определения шагов

 [Given(@"I have a valid token")]
public void method() {}

[When(@"I have a valid token")]
public void method() {}

[Then(@"I have a valid token")]
public void method(String name1, String insureanceId1, String name2, String insureanceId2) 
{

    // some code here
    
    var details = obj.Persons; // obj is an object of some other class where Person is residing in it
    
    // I have tried the following
    // I want to extend this for name2 and insuranceId2
    // In a nut shell, in the same testcase, I have to validate both names and insuranceId keys inside Persons JSONArray!
    
    foreach (item in details) 
    {
        item.Name.Should().Be(name1)
        item.InsuranceId.Should().Be(insuranceId1)
    }
    
    // P.S: tried this approach instead of using above foreach
    List<String> names = new List<String>();
    names.add(name1);
    names.add(name2);
    
    List<String> insuranceIds = new List<String>();
    insuranceIds.add(insuranceId1);
    insuranceIds.add(insuranceId2);
    
    for (int i = 0; i < details.size(); i  ) 
    {
        String expectedName = details[i].Name;
        String expectedInsruanceId = details[i].InsuranceId;
    
        String actualName = names[i];
        String actualInsuranceId = insuranceIds[i];
    
        expectedName.Should().Be(actualName);
        expectedInsruanceId.Should().Be(actualInsuranceId );
    }

}
 

Каков наилучший способ достичь этого? Используя лямбды (выберите)? Любые другие предложения, пожалуйста, помогите мне здесь!

Комментарии:

1. Как насчет name2, insuranceid2? Для чего они нужны?

2. Массив имеет два индекса, одно из которых содержит значение индекса Name2, insurnaceId2, в данном случае Name2 =JohnStash, insuranceId = N2789012. Я должен проверить имя и идентификатор insturanceId из обоих индексов и проверить на примерах из файла функций!

3. Спецпоток? Кто решил использовать SpecFlow?

4. Наш клиент lol, мы тестируем наши серверные API-сервисы, внедряя BDD через SpecFlow!

Ответ №1:

Использование горизонтальной таблицы данных на вашем Then шаге и использование помощников по таблицам должно помочь. Кроме того, я не вижу смысла использовать таблицу примеров (если только это не сокращенный пример сценария).

 Feature: To hit a GET endpoint and fetch the person details

@Feature-106
Scenario: Fetch the details and validate insurance Id
    Given I have a valid token
    When I create a GET request for /api/insuranceDetails
    Then the insurance details should be:
        | Name       | Insurance Id |
        | SteveBruns | M2409891     |
        | JohnStash  | N2789012     |
 

И определение шага довольно простое, если предположить, что заголовки столбцов таблицы данных SpecFlow соответствуют именам свойств каждого объекта Person в результате JSON:

 [@Then(@"Then the insurance details should be:")]
public void ThenTheInsuranceDetailsShouldBe(Table table)
{
    var details = obj.Persons; // obj is an object of some other class where Person is residing in it

    // if the order of the collection does not matter
    table.CompareToSet(details);

    // if order matters
    table.CompareToSet(details, true);
}
 

Поскольку ваш клиент хочет использовать разработку, основанную на поведении, подумайте о том, чтобы перефразировать свои действия, чтобы говорить на их деловом языке:

 @Feature-106
Scenario: Fetch the details and validate insurance Id
    Given I have a valid token
    When I request the insurance details
    Then the insurance details should be:
        | Name       | Insurance Id |
        | SteveBruns | M2409891     |
        | JohnStash  | N2789012     |
 

Конечная точка и тот факт, что это запрос GET, являются деталями реализации, которые не нужно сообщать в сценарии BDD. Сначала сосредоточьтесь на бизнес-процессе.

Комментарии:

1. Спасибо вам за ваш краткий ответ. Постараюсь и дам вам знать. На самом деле я смотрел на некоторых помощников SpecFlow assist. Может быть, это оно и есть. И пример сценария, которым я поделился, — это всего лишь пример, объясняющий проблему, фактические шаги отличаются, и из-за ограничений клиента я не суммировал правильные шаги. Возвращаясь к таблице, как указано, я должен сравнить эти значения с объектом в классе модели (который имеет часть ответа API). Если существует динамический способ обновления индексов и проверки значений, скажите name1 и name2. Я использовал традиционное для цикла. До этого проблема была с обновлением.

2. Чтобы быть точным, я должен сравнить два списка одновременно, проверив, есть ли в ответе массива name1, name2 и insuranceId1, insuranceId2.

3. Передача true в качестве второго параметра в CompareToSet(…) также будет утверждать, что порядок массива такой, как вы ожидаете, если это поможет.

4. Я пробовал это, как сравнить два значения в одном тесте? Потому что для данного сценария, если у нас есть таблица с 2 строками (исключая заголовок), она будет выполняться с двумя разными наборами данных, верно? Не уверен, что вы поняли мой вопрос, но, чтобы быть точным, мне нужно сравнить SteveBruns и JohnStash со значениями того же, что находится в ResponseObject, одновременно.