TL;DR
How do you test a value object in isolation from its dependencies without stubbing or injecting them?
In Misko Hevery's blog post To “new” or not to “new”… he advocates the following (quoted from the blog post):
- An Injectable class can ask for other Injectables in its constructor.(Sometimes I refer to Injectables as Service Objects, but that term is overloaded.). Injectable can never ask for a non-Injectable (Newable) in its constructor.
- Newables can ask for other Newables in their constructor, but not for Injectables (Sometimes I refer to Newables as Value Object, but again, the term is overloaded)
Now if I have a Quantity
value object like this:
class Quantity{
$quantity=0;
public function __construct($quantity){
$intValidator = new Zend_Validate_Int();
if(!$intValidator->isValid($quantity)){
throw new Exception("Quantity must be an integer.");
}
$gtValidator = new Zend_Validate_GreaterThan(0);
if(!$gtvalidator->isValid($quantity)){
throw new Exception("Quantity must be greater than zero.");
}
$this->quantity=$quantity;
}
}
My Quantity
value object depends on at least 2 validators for its proper construction. Normally I would have injected those validators through the constructor, so that I can stub them during testing.
However, according to Misko a newable shouldn't ask for injectables in its constructor. Frankly a Quantity
object that looks like this
$quantity=new Quantity(1,$intValidator,$gtValidator);
looks really awkward.
Using a dependency injection framework to create a value object is even more awkward. However now my dependencies are hard coded in the Quantity
constructor and I have no way to alter them if the business logic changes.
How do you design the value object properly for testing and adherence to the separation between injectables and newables?
Notes:
- This is just a very very simplified example. My real object my have serious logic in it that may use other dependencies as well.
- I used a PHP example just for illustration. Answers in other languages are appreciated.