The post is about a simple but useful way of writing tests against different implementations of a Repository interface. Assuming you have a PlayerRepository in your Domain (this is just an interface) and two implementations in the Infrastructure layer, InMemoryPlayerRepository and MongoPlayerRepository. The latter is used in production, the former is mainly for tests.
interface PlayerRepository {
boolean exists(PlayerId playerId);
}
class InMemoryPlayerRepository implements PlayerRepository {
@Override public boolean exists(PlayerId playerId) { ... }
}
class MongoPlayerRepository implements PlayerRepository {
@Override public boolean exists(PlayerId playerId) { ... }
}
I used to maintain different test suites for them, since MongoPlayerRepository required for example a running Mongo process and a running Spring application context, while the in-memory version did not. But most tests were identical so it was simply duplicated code. The solution I'm using nowadays is extracting the tests in an abstract test template class and do implementation specific test configuration in the subclasses.
abstract class AbstractPlayerRepositoryTestTemplate {
protected PlayerRepository testObj;
@Test
public void exists() {
// setup
...
//assert
assertTrue(testObj.exists(playerId));
}
}
class InMemoryPlayerRepositoryTest extends AbstractPlayerRepositoryTestTemplate {
@Before
public void before() {
testObj = new InMemoryPurchaseStore();
}
}
@ContextConfiguration("classpath:applicationContext-test.xml")
@RunWith(SpringJUnit4ClassRunner.class)
class MongoPlayerRepositoryITest extends AbstractPlayerRepositoryTestTemplate {
@Resource
private MongoPlayerRepository mongoRepository;
@Before
public void before() {
testObj = mongoRepository;
testObj.clear();
}
}
Of course you can use the approach for anything where there are multiple implementations of an interface, I just come across the need most frequently with Repositories.
No comments :
Post a Comment