0

Say I have a domain object like this:

public class Customer
{
    private Guid _id;
    private string _name;
    private Address _address;

    public Customer (Guid id, string name, Address address)
    {
       if (id == Guid.Empty)
                throw new ArgumentException();           
       if (name == "")
           throw new ArgumentException();
       if (address == null)
           throw new ArgumentException();
         _id = id;
        _address = address;
        _name= name;
    }
}

I want to create some Specflow scenarios to test this. So far I have done (Specflow scenario in feature file):

Given a name of Bert and an address of 1 The street, London, Greater London, L1 234 

This Specflow scenario looks ok to me, however I am conscious that I am missing out the ID. The ID is created inside the test method. Should I be doing this instead (specflow scenario in feature file):

Given a name of Bert and an address of 1 The street, London, Greater London, L1 234 and an id of 111-11-1111-11

The first approach (without the ID) looks correct to me. Am I right here? If I use the first approach, then how would I create a scenario to test for an empty ID?

Every single example I look at online shows how to apply Specflow to a simple Calculator or game. None of these classes have or need IDs.

3 Answers 3

1

I may be misunderstanding what a "domain object" is, but I'm assuming it's some sort of entity, ie its part of your application's model that is persisted to eg a database. Assuming that's correct, then it is an implementation detail.

Specflow is a tool for testing requirements/user stories. So Specflow shouldn't be used to test implementation details directly.

It then becomes a case of whether that customer ID is shared with the customer, such as in emails, order forms and the like. If it is, then its reasonable to suppose you'd have requirements, and thus Specflow scenarios, around handing locating a customer based on ID or address. It would be pretty weird though to have a requirement though that the only way to find a customer is to search on their name, address and ID.

Whereas if that ID isn't ever exposed to the customer, then you won't have requirements for it and thus it will not be of concern to Specflow.

Either way, one thing is certain: Specflow absolutely should not be being used to test for an empty ID.

4
  • Thanks +1 for: "Specflow absolutely should not be being used to test for an empty ID.". If I replaced the ID with an account number (used in the language of the domain), then I guess it could be specified in the Specflow scenario? Commented Mar 2, 2018 at 15:49
  • could you answer the question above before I mark the answer? Commented Mar 2, 2018 at 17:15
  • Yes, that is sort of what I meant by "[if the] customer ID is shared with the customer". I'd assume the account number would be used as the ID, as it's already a unique identifier. Commented Mar 2, 2018 at 17:22
  • I have asked another question, which follows from this one if you are interested: softwareengineering.stackexchange.com/questions/366937/… Commented Mar 3, 2018 at 9:52
1

I believe that, as a rule, you want to keep the logical separation between incidental implementation details and those bits of signal that are relevant to your test scenarios.

In your case, name and address are something you care about, but any id would be satisfactory. So I would expect your scenario to describe the name and the address, and let the implementation supply whatever id it likes.

See

2
  • Does "So I would expect your scenario to describe the name and the id" need changing to: "So I would expect your scenario to describe the name and the address"? Commented Mar 2, 2018 at 14:28
  • +1 for the hyperlinks. I have asked another question, which follows from this one if you are interested: softwareengineering.stackexchange.com/questions/366937/… Commented Mar 3, 2018 at 9:52
-2

I would change the domain object to be like this:

public class Customer
{
    public Guid Id;
    public string Name;
    public Address Address;

    public Customer ()
    {
        this.Id = Guid.NewGuid();
    }
}

When you create a new customer you always want a new and unique id.

If you are deserialising a customer object from a database or similar, you want to be able to set the individual fields.

This gives you the option of not worrying about what the Id is in your test and the assurance that the Id will always be populated

6
  • I guess I could have two constructors - one accepting just an name and address (for the specflow scenarios) and the other accepting an ID, Name and Address. Is that what you mean? Commented Mar 2, 2018 at 12:47
  • you could add an extra constructor, but I would just set the fields Commented Mar 2, 2018 at 12:55
  • If I am deserializing from the database, then the default constructor is still called? Wouldn't that mean the ID is overwritten with a new ID? Commented Mar 2, 2018 at 13:00
  • no becuase the constructor is called first, then you set the id Commented Mar 2, 2018 at 13:01
  • I see (I am use to writing ADO.NET rather than an ORM). Is it normal practice to create the ID in the zero arguments constructor? Commented Mar 2, 2018 at 13:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.