robustness principle and mocks
By traviscj
- 2 minutes read - 240 wordsThe Robustness Principle (or Postel’s Law) states
Be conservative in what you do, be liberal in what you accept from others (often reworded as “Be conservative in what you send, be liberal in what you accept”).
This principle has some criticisms.
I realized this has interesting implications for mocks. Suppose you have
public class MyObj {
private final Integer x;
public MyObj(Integer x) {
if (x < 0) {
throw new IllegalArgumentException("negative x!");
}
this.x = x;
}
public int getX() {
return x;
}
}
In a unit test, we can have
MyObj myObj = mock(MyObj.class);
when(myObj.getX()).thenReturn(-1);
which bypasses our sanity checks!
My takeaways from this are:
Don’t use mocks for POJO/data-ish objects!
If this feels painful, create a fixtures class:
public class MyObjFixtures {
@Inject Random random;
public MyObj create() {
return new MyObj(Math.abs(random.nextInt()));
}
}
Create “fake” implementations when possible/appropriate.
Usually, it’s quite a bit easier to create a fake implementation than a real implementation:
- use maps/lists instead of a real database
- take shortcuts like avoiding concurrency where possible
- depend on fakes of whatever API calls you need
There’s some danger in this – you should definitely consider wiring things up in a way that your tests can run against “real” implementations or sandboxes of them.
Another major concern becomes having a way to “reset” the fake implementations between tests to reduce flake, or coming up with a way to test that avoids the need to reset.