My question will be in the hand of a simplified example (in Java):
public class VehicleRepository {
How are you going to test this class? I thought about this a bit and I identified a few options:
Test against returned car without mocking the builder
From an interface point of view, this is the best option, but it will not be an isolated unit test on VehicleRepository. I see no real advantage for testing VehicleRepository with VehicleBuilder, and not just with VehicleBuilder validation. VehicleBuilder can also have complex logic (for example, checking for accessories), which leads to several execution paths and which makes the VehicleRepository test very difficult.
Code refactoring to check linker status
An example would be splitting the getLuxuryCar operation into two operations:
public Vehicle getLuxuryCar() { VehicleBuilder builder = getLuxuryCarBuilder(); return builder.build(); }
I prefer state testing to test behavior, and the test is likely to be more robust, but I don't really like the resulting code (especially the getLuxuryCar () method, which actually does nothing).
Give up VehicleBuilder and check the behavior
I believe that such a unit test will be just a copy of the actual operation, verified, and will not add any real benefit. It would also be very fragile and completely dependent on the internal elements of the operation being tested. Probably unit test (using JMock) will look something like this:
@Test public void shouldBuildLuxuryCar() { context.checking(new Expectations() {{ oneOf(chassisDAOmock).findBySize(ChassisSize.NORMAL); oneOf(vehicleBuilderMock).setChassis(with(any(Chassis.class))); oneOf(engineDAOmock).findByPower(EnginePower.HIGH); oneOf(vehicleBuilderMock).setEngine(with(any(Engine.class))); oneOf(wheelDAOmock).findBySize(WheelSize.NORMAL)); oneOf(vehicleBuilderMock).setWheelTemplate(with(any(Wheel.class))); oneOf(accessoryDAOmock).findByType(Accessory.LUXURY)); oneOf(vehicleBuilderMock).setAccessories(with(any(Set.class))); oneOf(vehicleBuilderMock).build(); }}); context.assertIsSatisfied(); }
Not unit test he
I am inclined to this option as I am not satisfied with any of the alternatives, and since the operations do not seem to require any testing. To clarify, I will still be unit test VehicleBuilder in isolation, but not VehicleRepository. However, this does not seem to be the prevailing opinion, which can be seen, for example, with this question: Device testing - what not to test