Chapter 1. The basics of unit testing
Listing 1.1. A simple parser class to test
Listing 1.2. A simple coded method that tests the SimpleParser class
Listing 1.3. Running coded tests via a simple console application
Listing 1.4. Using a more generic implementation of the ShowProblem method
Chapter 2. A first unit test
Listing 2.1. Using [SetUp] and [TearDown] attributes
Listing 2.2. The LogAnalyzer filename-validation logic we’d like to test
Listing 2.3. Testing the property value by calling IsValidLogFileName
Listing 2.4. Testing a class by calling a method and checking the value of a property
Listing 2.5. The Add() and Sum() methods
Listing 2.6. The simplest test for Calculator’s Sum()
Listing 2.7. The two tests, with the second one calling the Add() method
Chapter 3. Using stubs to break dependencies
Listing 3.1. Extracting a class that touches the filesystem, and calling it
Listing 3.2. Extracting an interface from a known class
Listing 3.3. Simple stub code that always returns true
Listing 3.4. Injecting our stub using constructor injection
Listing 3.5. Injecting a stub by adding property setters to the class under test
Listing 3.6. Setting a factory class to return a stub when the test is running
Listing 3.7. Faking a factory method
Listing 3.8. Returning a result rather than a stub object from an extracted method
Chapter 4. Interaction testing using mock objects
Chapter 5. Isolation (mock object) frameworks
Listing 5.1. Implementing complicated interfaces with handwritten stubs
Listing 5.2. Asserting against a handwritten mock object
Listing 5.3. Creating a dynamic mock object using Rhino Mocks
Listing 5.4. Creating a nonstrict mock
Listing 5.5. Returning a value from a mock object using the LastCall class
Listing 5.6. Creating a stub is remarkably similar to creating a mock object
Listing 5.7. Verifying expectations on a stub object can’t fail a test
Listing 5.8. Faking an exception using the LastCall class
Listing 5.9. The method under test and a test that uses handwritten mocks and stubs
Listing 5.10. Converting the previous test into one that uses dynamic mocks and stubs
Listing 5.11. Using a string constraint in a test
Listing 5.12. Using the Property constraints by using the Property static class
Listing 5.13. Combining constraints with And and Or
Listing 5.14. Comparing full objects
Listing 5.15. Using an anonymous delegate to verify a parameter
Listing 5.16. Using a regular method instead of an anonymous delegate
Listing 5.17. Testing that an event was registered properly
Listing 5.18. Triggering an event via the EventRaiser class in Rhino Mocks
Listing 5.19. Using an anonymous delegate to register to an event
Listing 5.20. Using the EventsVerifier class to test for event values
Chapter 6. Test hierarchies and organization
Listing 6.1. An example of not following the DRY principle in test classes
Listing 6.2. A refactored solution
Listing 6.3. A derived test class with its own setup method
Listing 6.4. Overriding a setup method purely for clarity
Listing 6.5. An outline of a test class for StandardStringParser
Listing 6.6. An abstract test base class with test logic for IStringParser interface
Listing 6.7. A derived test class that overrides a small number of factory methods
Listing 6.8. Implementing test case inheritance with .NET generics
Chapter 7. The pillars of good tests
Listing 7.1. A simple test against the LogAnalyzer class
Listing 7.2. The changed test using the new semantics of LogAnalyzer
Listing 7.3. A refactored test using a factory method
Listing 7.4. A test with multiple asserts
Listing 7.5. A class under test, and a test that uses it
Listing 7.6. Two tests with duplication
Listing 7.7. LogAnalyzer with changed semantics that now requires initialization
Listing 7.8. Adding the Initialize() call in the factory method
Listing 7.9. Using a setup method to remove duplication
Listing 7.10. A poorly implemented Setup() method
Listing 7.11. Constrained test order: the second test will fail if it runs first
Listing 7.12. One test calling another breaks isolation and introduces a dependency
Listing 7.13. Shared-state corruption by a test
Listing 7.14. A test that contains multiple asserts
Listing 7.15. A refactored test class with three different tests
Listing 7.16. A refactored test class using parameterized tests
Listing 7.17. Testing multiple aspects of the same object in one test
Listing 7.18. Comparing objects instead of using multiple asserts
Listing 7.19. Implementing ToString() in compared classes for cleaner output
Listing 7.20. An overspecified test that tests a purely internal behavior
Listing 7.21. An overspecified test that uses mocks when stubs would do fine
Listing 7.22. Replacing mocks with stubs and checking outputs instead of interactions
Listing 7.23. A test with three parts in its name
Listing 7.24. An unreadable test name
Listing 7.25. A more readable version of the test
Listing 7.26. A bad assert message that repeats what the test framework outputs
Listing 7.27. Separating the assert from the thing asserted improves readability
Listing 7.28. Not separating the assert from the thing asserted makes reading difficult
Chapter 9. Working with legacy code
Listing 9.1. Faking static methods and creating fake classes with Isolator
Listing 9.2. Using JMockit to swap class implementations
Listing 9.3. Using Vise in Java code to verify values aren’t changed while refactoring
Appendix A. Design and testability
Listing A.1. A class that invokes a delegate that can be replaced by a test
Listing A.2. An untestable singleton design
Listing A.3. The singleton class refactored into a testable design
52.15.129.253