I have a spring boot app with autowired components. It works fine operationally, but mocking is not initializing the components properly. Here are the main components:
base processor:
@Component
public class Processor {
public String getType() { return null; }
public void transformInput(JsonObject data) { }
public void buildOutputRequest(String syncType) { }
}
, one of the 4 subtypes:
@Component
public class ProcessorType1 extends Processor {
@Override
public String getType() { return Type.TYPE1.getValue();}
public void transformInput(JsonObject data) {
// do dtuff
}
}
, supporting enum:
public enum Type {
TYPE1("TYPE1"),TYPE2("TYPE2"), TYPE3("TYPE3"), TYPE4("TYPE4");
private final String value;
public static final Map<Type, String> enumMap = new EnumMap<Type, String>(
Type.class);
static {
for (Type e : Type.values())
enumMap.put(e, e.getValue());
}
Type(String value) { this.value = value;}
public String getValue() { return value; }
}
,and the factory class:
@Component
public class ProcessorFactory {
@Autowired
public ProcessorFactory(List<Processor> processors) {
for (Processor processor : processors) {
processorCache.put(processor.getType(), processor);
}
}
private static final Map<String, Processor> processorCache = new HashMap<String, Processor>();
public static Processor getProcessor(String type) {
Processor service = processorCache.get(type);
if(service == null) throw new RuntimeException("Unknown type: " + type);
return service;
}
}
, then operationally, a calling service uses the factory similar to this:
@Service
MyService {
public processData (
// do stuff to get processor type and data
Processor processor = ProcessorFactory.getProcessor(type);
processor.transformInput(data);
)
}
Again, operationally this works fine. However, I attempt to mock the factory and its initialization like the following:
@RunWith(SpringJUnit4ClassRunner.class)
public class ProcessorFacTest
{
@InjectMocks
ProcessorFactory factory;
@Test
void testGetSyncProcessorDocument() {
String type = Type.TYPE1.getValue();
Processor processor = ProcessorFactory.getProcessor(type);
Assert.assertTrue(processor instanceof ProcessorType1);
}
}
My expectation was that since I am using @InjectMocks, and since ProcessorFactory has its constructor autowired, the constructor would be called by InjectMocks as part of the initialization. However, this is not happening. The processorCache is zero-length because the constructor is never called.
I realize I am mixing injection with static usages, but since it worked operationally, and since my understanding was that InjectMocks would handle the creation of the processorCache, that it should have worked for the test class as well, and its not.
I would be grateful for any ideas as to what I am doing wrong. Thank you