我正在尝试针对一个类编写单元测试。我无法更改类,但是我认为可以使用反射进行测试。我只是不知道该怎么做。这是课程:
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.");
}
}
}
到目前为止,这是我所要做的测试……不确定如何实际执行。
@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);
}
}
是否可以为此使用白盒?我需要确保在这些对象的getter内部有一个调用。我是否应该尝试诸如when(someOtherClassProcessor01.doSomething(any(),date))。thenReturn(true)之类的事情?如果您需要更多详细信息,请告诉我。
编辑:甚至可以模拟私有枚举SomeTypes?
答案 0 :(得分:3)
一种选择是使用反射将SomeOtherClassProcessor
的自己(模拟)实现替换为MyClass
:
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。使用PowerMock和/或反射会屈服于不良设计(根据Timothy的说法)。您不应该依赖尚未经过充分测试的代码,如果是这样,则不应尝试再次对其进行测试。假设您的测试实际上揭示了一个错误-如果您不控制代码,该如何解决?假设Java 11成为一件事,并禁止您使用反射。假设您要测试的代码已更改,并且字段已重命名-通过反射,您就没有编译时的安全性……潜在问题清单还在继续