SpecFlow and complex objects

Ramunas picture Ramunas · Apr 26, 2011 · Viewed 31.3k times · Source

I'm evaluating SpecFlow and I'm a bit stuck.
All samples I have found are basically with simple objects.

Project I'm working on heavily relies on a complex object. A close sample could be this object:

public class MyObject
{
    public int Id { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public IList<ChildObject> Children { get; set; }

}

public class ChildObject
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Length { get; set; }
}

Does anyone have any idea how could a write my features/scenarios where MyObject would be instantiated from a "Given" step and used in "When" and "Then" steps?

Thanks in advance

EDIT: Just a shot in mind: are nested tables supported?

Answer

stuartf picture stuartf · Apr 26, 2011

I would say that Marcus is pretty much correct here, however I would write my scenario so that I could use some of the extensions methods for in the TechTalk.SpecFlow.Assist namespace. See here.

Given I have the following Children:
| Id | Name | Length |
| 1  | John | 26     |
| 2  | Kate | 21     |
Given I have the following MyObject:
| Field     | Value      |
| Id        | 1          |
| StartDate | 01/01/2011 |
| EndDate   | 01/01/2011 |
| Children  | 1,2        |

For the code behind the steps you could use something like this will a bit more error handling in it.

    [Given(@"I have the following Children:")]
    public void GivenIHaveTheFollowingChildren(Table table)
    {
        ScenarioContext.Current.Set(table.CreateSet<ChildObject>());
    }


    [Given(@"I have entered the following MyObject:")]
    public void GivenIHaveEnteredTheFollowingMyObject(Table table)
    {
        var obj = table.CreateInstance<MyObject>();
        var children = ScenarioContext.Current.Get<IEnumerable<ChildObject>>();
        obj.Children = new List<ChildObject>();

        foreach (var row in table.Rows)
        {
            if(row["Field"].Equals("Children"))
            {
                foreach (var childId in row["Value"].Split(new char[]{','}, StringSplitOptions.RemoveEmptyEntries))
                {
                    obj.Children.Add(children
                        .Where(child => child.Id.Equals(Convert.ToInt32(childId)))
                        .First());
                }
            }
        }
    }

Hope this (or some of this) help to you