I need to write a test PartitionMapperTest
for my Java class PartitionMapper
. This class has private fields with @Inject
annotations but it has only a no-param constructor.
For the test, I want to create a partitionMapper
before any test and inject values into its private fields. Then, tester tests the mapper's method mapPartitions
and assert values. However, I don't know how to inject these values into partitionMapper
.
PartitionMapper.java
@Named
public class PartitionMapper implements javax.batch.api.partition.PartitionMapper {
@Inject
private JobContext jobContext;
@Inject
@BatchProperty
private String fetchSize;
@Inject
@BatchProperty
private String rowsPerPartition;
// other batch properties ...
@PersistenceUnit(unitName = "h2")
private EntityManagerFactory emf;
@Override
public PartitionPlan mapPartitions() throws Exception {
// ...
}
}
PartitionMapperTest.java
public class PartitionMapperTest {
private PartitionMapper partitionMapper;
@Before
public void setUp() {
// Prepare JobContext, batch properties to inject ...
// Instantiation
partitionMapper = new PartitionMapper();
// TODO How to inject these objects into partitionMapper?
}
@Test
public void testMapPartitions() throws Exception {
PartitionPlan partitionPlan = partitionMapper.mapPartitions();
for (Properties p : partitionPlan.getPartitionProperties()) {
// Assertions here ...
}
}
// ...
}
I actually did implement a real PartitionMapperTest
based on Mockito and PowerMock, which can be seen on my GitHub. The problem is there're so many assumptions that it leads to very poor code for user-understanding. I'm looking for another solution for refactoring it.
Is there any reason to only have a no args constructor?
I would recommand you to use constructor injection instead of field injection. That would solve you problem.
For example instead of:
public class Foo {
@Inject
private Bar bar;
}
do this:
public class Foo {
private Bar bar;
public Foo(@Inject Bar bar) {
this.bar = bar;
}
}
If you define your injection points this way you have a clean API and your class can be used in non-cdi environments (like unit-tests).
There are many resources about "constructor injection VS field injection"... Also on stackoverflow, e.g. https://stackoverflow.com/a/19382081/4864870.