Download at WoweBookCom
Data Matrix ECC200 Creation In JavaUsing Barcode drawer for Java Control to generate, create DataMatrix image in Java applications.
Emphasizing the Domain Model with Factory Methods
Making Barcode In JavaUsing Barcode drawer for Java Control to generate, create barcode image in Java applications.
Combining Builders
Barcode Recognizer In JavaUsing Barcode decoder for Java Control to read, scan read, scan image in Java applications.
Where a test data builder for an object uses other built objects, we can pass in those builders as arguments rather than their objects This will simplify the test code by removing the build() methods The result is easier to read because it emphasizes the important information what is being built rather than the mechanics of building it For example, this code builds an order with no postcode, but it s dominated by the builder infrastructure:
Data Matrix Maker In Visual C#Using Barcode generation for .NET framework Control to generate, create Data Matrix image in .NET framework applications.
Order orderWithNoPostcode = new OrderBuilder() fromCustomer( new CustomerBuilder() withAddress(new AddressBuilder()withNoPostcode()build()) build()) build();
Encode DataMatrix In Visual Studio .NETUsing Barcode generator for ASP.NET Control to generate, create ECC200 image in ASP.NET applications.
We can remove much of the noise by passing around builders:
Data Matrix Generator In Visual Studio .NETUsing Barcode printer for .NET Control to generate, create DataMatrix image in .NET applications.
Order order = new OrderBuilder() fromCustomer( new CustomerBuilder() withAddress(new AddressBuilder()withNoPostcode()))) build();
Data Matrix Generation In Visual Basic .NETUsing Barcode encoder for VS .NET Control to generate, create DataMatrix image in .NET framework applications.
Emphasizing the Domain Model with Factory Methods
Making Bar Code In JavaUsing Barcode generator for Java Control to generate, create bar code image in Java applications.
We can further reduce the noise in the test code by wrapping up the construction of the builders in factory methods:
GS1 128 Creator In JavaUsing Barcode creator for Java Control to generate, create UCC.EAN - 128 image in Java applications.
Order order = anOrder()fromCustomer( aCustomer()withAddress(anAddress()withNoPostcode()))build();
Print EAN13 In JavaUsing Barcode drawer for Java Control to generate, create European Article Number 13 image in Java applications.
As we compress the test code, the duplication in the builders becomes more obtrusive; we have the name of the constructed type in both the with and builder methods We can take advantage of Java s method overloading by collapsing this to a single with() method, letting the Java type system gure out which eld to update:
UPC A Printer In JavaUsing Barcode maker for Java Control to generate, create UCC - 12 image in Java applications.
Order order = anOrder()from(aCustomer()with(anAddress()withNoPostcode()))build();
Data Matrix 2d Barcode Generator In JavaUsing Barcode maker for Java Control to generate, create Data Matrix image in Java applications.
Obviously, this will only work with one argument of each type For example, if we introduce a Postcode, we can use overloading, whereas the rest of the builder methods must have explicit names because they use String:
Generate C 2 Of 5 In JavaUsing Barcode encoder for Java Control to generate, create 2 of 5 Industrial image in Java applications.
Address aLongerAddress = anAddress() withStreet("221b Baker Street") withCity("London") with(postCode("NW1", "3RX")) build();
Code 3/9 Maker In VB.NETUsing Barcode encoder for Visual Studio .NET Control to generate, create Code 39 Extended image in VS .NET applications.
Download at WoweBookCom
Generate Bar Code In .NETUsing Barcode maker for ASP.NET Control to generate, create barcode image in ASP.NET applications.
22
Paint EAN-13 Supplement 5 In .NET FrameworkUsing Barcode encoder for ASP.NET Control to generate, create EAN-13 Supplement 5 image in ASP.NET applications.
Constructing Complex Test Data
USS Code 128 Generator In .NET FrameworkUsing Barcode maker for ASP.NET Control to generate, create Code 128 Code Set B image in ASP.NET applications.
This should encourage us to introduce domain types, which, as we wrote in Domain Types Are Better Than Strings (page 213), leads to more expressive and maintainable code
Decoding USS Code 39 In .NET FrameworkUsing Barcode decoder for .NET Control to read, scan read, scan image in .NET applications.
Removing Duplication at the Point of Use
Painting Barcode In Visual C#.NETUsing Barcode creation for .NET framework Control to generate, create barcode image in .NET applications.
We ve made the process of assembling complex objects for tests simpler and more expressive by using test data builders Now, let s look at how we can structure our tests to make the best use of these builders in context We often nd ourselves writing tests with similar code to create supporting objects and pass them to the code under test, so we want to clean up this duplication We ve found that some refactorings are better than others; here s an example
Code 128C Drawer In VB.NETUsing Barcode encoder for .NET framework Control to generate, create Code 128 image in .NET framework applications.
First, Remove Duplication
We have a system that processes orders asynchronously The test feeds orders into the system, tracks their progress on a monitor, and then looks for them in a user interface We ve packaged up all the infrastructure so the test looks like this:
@Test public void reportsTotalSalesOfOrderedProducts() { Order order1 = anOrder() withLine("Deerstalker Hat", 1) withLine("Tweed Cape", 1) withCustomersReference(1234) build(); requestSendersend(order1); progressMonitorwaitForCompletion(order1); Order order2 = anOrder() withLine("Deerstalker Hat", 1) withCustomersReference(5678) build(); requestSendersend(order2); progressMonitorwaitForCompletion(order2); TotalSalesReport report = guiopenSalesReport(); reportcheckDisplayedTotalSalesFor("Deerstalker Hat", is(equalTo(2))); reportcheckDisplayedTotalSalesFor("Tweed Cape", is(equalTo(1))); }
There s an obvious duplication in the way the orders are created, sent, and tracked Our rst thought might be to pull that into a helper method:
@Test public void reportsTotalSalesOfOrderedProducts() { submitOrderFor("Deerstalker Hat", "Tweed Cape"); submitOrderFor("Deerstalker Hat"); TotalSalesReport report = guiopenSalesReport(); reportcheckDisplayedTotalSalesFor("Deerstalker Hat", is(equalTo(2))); reportcheckDisplayedTotalSalesFor("Tweed Cape", is(equalTo(1))); }
Download at WoweBookCom
Removing Duplication at the Point of Use
void submitOrderFor(String products) { OrderBuilder orderBuilder = anOrder() withCustomersReference(nextCustomerReference()); for (String product : products) { orderBuilder = orderBuilderwithLine(product, 1); } Order order = orderBuilderbuild(); requestSendersend(order); progressMonitorwaitForCompletion(order); }
This refactoring works ne when there s a single case but, like the object mother pattern, does not scale well when we have variation As we deal with orders with different contents, amendments, cancellations, and so on, we end up with this sort of mess:
void submitOrderFor(String products) { [ ] void submitOrderFor(String product, int count, String otherProduct, int otherCount) { [ ] void submitOrderFor(String product, double discount) { [ ] void submitOrderFor(String product, String giftVoucherCode) { [ ]
We think a bit harder about what varies between tests and what is common, and realize that a better alternative is to pass the builder through, not its arguments; it s similar to when we started combining builders The helper method can use the builder to add any supporting detail to the order before feeding it into the system:
@Test public void reportsTotalSalesOfOrderedProducts() { sendAndProcess(anOrder() withLine("Deerstalker Hat", 1) withLine("Tweed Cape", 1)); sendAndProcess(anOrder() withLine("Deerstalker Hat", 1)); TotalSalesReport report = guiopenSalesReport(); reportcheckDisplayedTotalSalesFor("Deerstalker Hat", is(equalTo(2))); reportcheckDisplayedTotalSalesFor("Tweed Cape", is(equalTo(1))); } void sendAndProcess(OrderBuilder orderDetails) { Order order = orderDetails withDefaultCustomersReference(nextCustomerReference()) build(); requestSendersend(order); progressMonitorwaitForCompletion(order); }