I'm trying to write unit test against a class. I can't change the class, but I think it's possible to test using reflection. I just don't know how to do it. Here's the class:
public class MyClass extends AnotherClass implements TheInterface
{
private enum SomeTypes
{
SAMPLE01, SAMPLE02, SAMPLE03
}
private CircularList<SomeTypes> someTypesList;
Date date= new Date();
private SomeOtherClassProcessor01 someOtherClassProcessor01;
private SomeOtherClassProcessor02 someOtherClassProcessor02;
private SomeOtherClassProcessor03 someOtherClassProcessor03;
public Properties initialize (Properties properties) throws Exception
{
Properties propertiesToReturn = super.initialize(properties);
someTypesList = new CircularList<SomeTypes> (Arrays.asList(SomeTypes.values()));
someOtherClassProcessor01 = new SomeOtherClassProcessor01();
someOtherClassProcessor02 = new SomeOtherClassProcessor02();
someOtherClassProcessor03 = new SomeOtherClassProcessor03();
return propertiesToReturn;
}
@Override
public void get(ImportedClass someParams) throws Exception
{
SomeTypes types = someTypesList.getFirstAndRotate();
switch(types)
{
case SAMPLE01:
someOtherClassProcessor01.doSomething(someParams, date);
break;
case SAMPLE02:
someOtherClassProcessor02.doSomething(someParams, date);
break;
case SAMPLE03:
someOtherClassProcessor03.doSomething(someParams, date);
break;
default:
throw new IllegalArgumentException("This " + types + " was not implemented.");
}
}
}
For my test this is what I have so far... not sure how to actually do it.
@RunWith(PowerMockRunner.class)
@PrepareForTest(MyClass.class)
public class TestingMyClass
{
MyClass mockMyClass;
SomeOtherClassProcessor01 someOtherClassProcessor01;
SomeOtherClassProcessor02 someOtherClassProcessor02;
SomeOtherClassProcessor03 someOtherClassProcessor03;
Date date;
@Before
public void initialize () throws Exception
{
mockMyClass = spy(new MyClass());
mockSomeOtherClassProcessor01 = mock(SomeOtherClassProcessor01.class);
mockSomeOtherClassProcessor02 = mock(SomeOtherClassProcessor02.class);
mockSomeOtherClassProcessor03 = mock(SomeOtherClassProcessor03.class);
}
@Test
public void testingGet() throws Exception
{
date = new Date();
//this is where I'm stuck
Whitebox.setInternalState(mockMyClass, "someOtherClassProcessor01", mockSomeOtherClassProcessor01);
}
}
Would it be possible to use whitebox for this? I need to make sure that there's a call inside the getter for those objects. Should I try something like when(someOtherClassProcessor01.doSomething(any(), date)).thenReturn(true)? Please let me know if you need more details.
edit: is even possible to mock private enum SomeTypes?
One option is to substitute your own (mocked) implementations of SomeOtherClassProcessor
into MyClass
using reflection:
MyClass myClass = new MyClass();
SomeOtherProcessor01 mockProcessor01 = mock(SomeOtherProcessor01.class);
// reflection bit: find the field by its name
// handle NoSuchFieldException
Field someProcessorField = MyClass.getDeclaredField("someOtherProcessor01");
// the field is declared as private, so make it accessible in order to work with it
someProcessorField.setAccessible(true);
// now set your mocked processor into the field.
// First argument is the object to change; second argument - new value for the field
someProcessorField.set(myClass, mockProcessor01);
PS. Using PowerMock and/or reflection is surrender to bad design (as per Timothy :). You should not be depending on code you that isn't already well-tested, and if it is, you shouldn't try to test it again. Suppose your testing actually reveals a bug - how would you fix it if you don't control the code? Suppose Java 11 becomes a thing and prohibits your use of reflection. Suppose the code you're testing changes and the fields get renamed - with reflection, you don't have compile-time safety... List of potential issues goes on