Re: How do I use tables to generate a custom IEnumerable with SpecFlow.Assist ?

2,179 views
Skip to first unread message

Darren Cauthon

unread,
Feb 27, 2013, 10:20:27 AM2/27/13
to spec...@googlegroups.com
Hi Leland,

I'm sorry for the trouble you're having.  I don't know how to fix it, but I can explain the problem and perhaps offer a suggestion.

The problem is that the CreateSet method uses only a default constructor (with no arguments) to instantiate the objects.  If you added the following constructor to your object:

    public class Product{
        public Product(){
        }
        // ... everything else you already have
    }

Then CreateSet<T> will work for you.

Just because you say you are new:  With C#, every class you create gets a default constructor... *unless* you create your own.  So if you just make a class like this:

    public Product(){
    }

you can instantiate it with Product.new().  But if you create a constructor like yours, the default one goes away.  If you want it, you'll have to add it yourself with the code I listed above.

I hope that helps,


Darren


On Wednesday, February 27, 2013 8:08:36 AM UTC-6, Leland Schick wrote:
I'm trying to use SpecFlow.Assist with a custom class in C#, along with Mbunit, and my tests are all failing but for trivial reasons. The example I have is like this (I'm using the example from the documentation to explain the problem). Here's the SpecFlow Feature step:
Given these products exist
| Sku              | Name             | Price |
| BOOK1            | Atlas Shrugged   | 25.04 |
| BOOK2            | The Fountainhead | 20.15 |
And here's the step definition, using SpecFlow.Assist to make an IEnumerable of the Product class:
[Given(@"Given these products exist")]
public void x(Table table)
{
    var products = table.CreateSet<Product>();
    // ...
}
And finally, here's the very basic class definition,
public class Product
    {
        public Product(string sku, string name, double price)
        {
            this.Sku = sku;
            this.Name = name;
            this.Price = price;
        }

        
        public string Sku { get; set; }
        public string Name { get; set; }
        public double Price { get; set; }
This compiles fine, but when I try to run the tests, they all fail because at the first step there is an error which reads, "Unable to find suitable constructor to create instance of Product."   What kind of constructor should I write so that it can be used by the CreateSet method to generate an IEnumerable<Product>? Maybe I'm doing something basic wrong (I am very new with SpecFlow, and even .NET programming in general

Darren Cauthon

unread,
Feb 27, 2013, 10:22:22 AM2/27/13
to spec...@googlegroups.com
I'm sorry -- I have Ruby on the brain right now.

I meant, with a default constructor you can instantiate an object with "new Product();"

:)

Darren Cauthon

unread,
Feb 27, 2013, 2:46:58 PM2/27/13
to spec...@googlegroups.com

CreateSet<Product>() should set the Sku property on the product to whatever is in the table -- not to null.

Think about it this way.  If you type:

    var product = new Product();

you'll get a product where product.Sku == null.

If you typed 'product.Sku == "BOOK1";' then product.Sku would equal "BOOK1"

That's what CreateSet<Product> does... it will run the "new Product() for each record in the table, and then it will look for matches.  If you have a column named "Sku" it will use  the ".Sku = value" to set it.


Darren

On Wednesday, February 27, 2013 11:35:02 AM UTC-6, Leland Schick wrote:
Well, now I have a new problem. The default constructor automatically assigns the Sku of each book to be null, instead of the desired Sku listed in the table. This leads to problems later on, as I use the Sku to search for specific members of the set. How do I modify either the constructor or the call to CreateSet so that instead of placing nulls in the Sku, it places the required values ("BOOK1", "BOOK2") in the Sku property?
Reply all
Reply to author
Forward
0 new messages