I have a model class in c# as shown below:
public class Persons {
public String Name {get; set;}
public int Age {get; set;}
public String InsuranceId {get; set;}
}
I am deserializing a part of API response in this class.
{
"persons": [
{
"name": "SteveBruns",
"age": 24,
"insuranceId": "M2409891"
},
{
"name": "JohnStash",
"age": 34,
"insuranceId": "N2789012"
}
]
}
I have to validate all the name and insuranceId fields, in my SpecFlow project. Let us say that we have a feature file as follows:
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 |
These are the step definitions
[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 );
}
}
What is the best way to achieve this? Using Lambdas (select)? Any other suggestions, please help me here!
Using a horizontal data table in your Then step and utilizing the table helpers should do the trick. Plus, I don't see a use for an examples table (unless this is an abbreviated example of the scenario).
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 |
And the step definition is pretty easy, assuming the column headers of the SpecFlow data table match the property names of each Person object in the JSON result:
[@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);
}
Since your client wants to use Behavior-Driven Development, consider rephrasing your steps to speak their business language:
@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 |
The endpoint and the fact it is a GET request is an implementation detail that doesn't need to be communicated in a BDD scenario. Focus on the business process first.