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.

w0051977
  • 7,031
  • 6
  • 59
  • 87

3 Answers3

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

VoiceOfUnreason
  • 32,131
  • 2
  • 42
  • 79
  • 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"? – w0051977 Mar 02 '18 at 14:28
  • +1 for the hyperlinks. I have asked another question, which follows from this one if you are interested: https://softwareengineering.stackexchange.com/questions/366937/testing-a-class-that-only-has-one-field-only-that-is-an-id-number – w0051977 Mar 03 '18 at 09:52
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.

David Arno
  • 38,972
  • 9
  • 88
  • 121
  • 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? – w0051977 Mar 02 '18 at 15:49
  • could you answer the question above before I mark the answer? – w0051977 Mar 02 '18 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. – David Arno Mar 02 '18 at 17:22
  • I have asked another question, which follows from this one if you are interested: https://softwareengineering.stackexchange.com/questions/366937/testing-a-class-that-only-has-one-field-only-that-is-an-id-number – w0051977 Mar 03 '18 at 09: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

Ewan
  • 70,664
  • 5
  • 76
  • 161
  • 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? – w0051977 Mar 02 '18 at 12:47
  • you could add an extra constructor, but I would just set the fields – Ewan Mar 02 '18 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? – w0051977 Mar 02 '18 at 13:00
  • no becuase the constructor is called first, then you set the id – Ewan Mar 02 '18 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? – w0051977 Mar 02 '18 at 13:02
  • normal for me *shrug* – Ewan Mar 02 '18 at 13:06