Test Data Builder versus Object Mother
September 30, 2007When writing unit tests, I frequently have an issue with creating objects that contain some test data. One approach is to call the constructor of the class at hand in every test case, like so:
[Test]
public void TestCase1()
{
Customer customer = new Customer("Homer", "Simpson");
// further implementation
}
[Test]
public void TestCase2()
{
Customer customer = new Customer(null, "Simpson");
// further implementation
}
[Test]
public void TestCase3()
{
Customer customer = new Customer("Homer", null);
// further implementation
}
The problem with this approach becomes clear when adding a new argument to the constructor of the Customer class. Now I have to make a change to all tests that create a Customer object.
What I did to overcome this issue, was to use the Object Mother pattern. I created a static class called TestFactory with a bunch of constant fields and methods that create all kinds of objects:
internal static class TestFactory
{
public const String FirstName = "Homer";
public const String LastName = "Simpson";
private static Customer CreateCustomer(String firstName,
String lastName)
{
return new Customer(firstName, lastName);
}
public static Customer CreateValidCustomer()
{
return CreateCustomer(FirstName, LastName);
}
public static Customer CreateCustomerWithoutFirstName()
{
return CreateCustomer(null, LastName);
}
public static Customer CreateCustomerWithoutLastName()
{
return CreateCustomer(FirstName, null);
}
}
I didn't really like this approach. For every special case, I needed to add another factory method. I couldn't come up with something better either at the time, so ... until I read this fine article yesterday. Instead of using the Object Mother pattern, the author uses the Builder pattern.
public class CustomerBuilder
{
public String _firstName = "Homer";
public String _lastName = "Simpson";
public CustomerBuilder WithFirstName(String firstName)
{
_firstName = firstName;
return this;
}
public CustomerBuilder WithLastName(String lastName)
{
_lastName = lastName;
return this;
}
public Customer Build()
{
return new Customer(_firstName, _lastName);
}
}
The tests itself would look like this:
[Test]
public void TestCase1()
{
Customer customer = new CustomerBuilder().Build();
// further implementation
}
[Test]
public void TestCase2()
{
Customer customer = new CustomerBuilder()
.WithFirstName(null)
.Build();
// further implementation
}
[Test]
public void TestCase3()
{
Customer customer = new CustomerBuilder()
.WithLastName(null)
.Build();
// further implementation
}
Looks pretty neat huh? If you're interested in writing maintainable unit tests, then you should definitely give the article a good read. The examples are written in Java, so I don't know if that has got anything to do with it :-).
If you and your team want to learn more about how to write maintainable unit tests and get the most out of TDD practices, make sure to have look at our trainings and workshops or check out the books section. Feel free to reach out at info. @ principal-it .be
Jan Van Ryswyck
Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.
Comments
Writing Maintainable
Unit Tests
Watch The Videos
Latest articles
-
Contract Tests - Parameterised Test Cases
June 28, 2023
-
Contract Tests - Abstract Test Cases
April 12, 2023
-
Contract Tests
February 1, 2023
-
The Testing Quadrant
June 15, 2022
-
Tales Of TDD: The Big Refactoring
February 2, 2022
Tags
- .NET
- ALT.NET
- ASP.NET
- Agile
- Announcement
- Architecture
- Behavior-Driven Development
- C++
- CQRS
- Clojure
- CoffeeScript
- Community
- Concurrent Programming
- Conferences
- Continuous Integration
- Core Skills
- CouchDB
- Database
- Design Patterns
- Domain-Driven Design
- Event Sourcing
- F#
- Fluent Interfaces
- Functional Programming
- Hacking
- Humor
- Java
- JavaScript
- Linux
- Microsoft
- NHibernate
- NoSQL
- Node.js
- Object-Relational Mapping
- Open Source
- Reading
- Ruby
- Software Design
- SourceControl
- Test-Driven Development
- Testing
- Tools
- Visual Studio
- Web
- Windows
Disclaimer
The opinions expressed on this blog are my own personal opinions. These do NOT represent anyone else’s view on the world in any way whatsoever.
About
Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Author of Writing Maintainable Unit Tests. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Thinking and learning about all kinds of technologies since forever.
Latest articles
Contract Tests - Parameterised Test Cases
Contract Tests - Abstract Test Cases
Contract Tests
The Testing Quadrant
Contact information
(+32) 496 38 00 82
info @ principal-it .be