我有这个原始代码:
public SomeClass(int parameter) {
this.someProperty = parameter;
this.apiObject = new SomeApiClass(someProperty);
for(i=0; i < 2; i++)
apiObject.setApiProperty(i, "Hello World");
}
代码完美无缺。但是当我尝试测试时会出现问题。
@Mock
private SomeApiClass someApiClass;
private SomeClass someClass;
@Before
public void setUp() throws Exception {
someClass = new SomeClass(3);
}
@Test
public void shouldCreateSomeClass() {
verify(someApiClass, times(2)). setApiProperty(anyInt(),anyString());
}
我理解为什么这个测试不会通过。如果我将构造函数更改为:
,这将有效public SomeClass(int parameter, SomeApiClass someApiClass) {
...
}
如果我不想将SomeApiClass
注入构造函数并且无法在其中提供任何getter,我如何测试原始代码。
PS:请忽略代码中的拼写错误。即时输入。
答案 0 :(得分:2)
在设计类时考虑可测试性以及区分参数和依赖性是很好的。
依赖关系是类依赖于完成其工作的对象。它们通常不会在依赖对象的整个生命周期内发生变化。
参数比依赖项更本地化。预计它们会在对对象方法的调用之间发生变化。
在原始代码中,看起来SomeClass
的构造函数中的工作应该真正进入方法:
public class SomeClass {
public void doWork(int parameter) {
//
}
}
在方法内部,如果您只对使用参数实例化SomeApiObject
感兴趣,那么为什么不遵循Demeter法则并直接传递SomeApiObject
作为参数:
public void doWork(SomeApiObject someApiObject) {
//
}
然后消费者完成工作:
someClass.doWork(new SomeApiObject(3));
可以通过传入模拟的SomeApiObject
作为参数进行测试:
//act
someClass.doWork(mockedSomeApiObject);
//assert
verify(mockedSomeApiObject).someVerification();
但是,如果您想要参数和依赖项的组合,可以使用Factory作为依赖项:
public class SomeClass {
private final SomeApiObjectFactory someApiObjectFactory;
public SomeClass(SomeApiObjectFactory someApiObjectFactory) {
this.someApiObjectFactory = someApiObjectFactory;
}
public void doWork(int parameter) {
SomeApiObject someApiObject = someApiObjectFactory.create(parameter);
//etc
}
然后你现在可以测试这个类了,因为你有办法提供可以验证哪些行为的模拟:
SomeApiObject mockSomeApiObject = Mockito.mock(SomeApiObject.class);
when(mockSomeApiObjectFactory.create(anyInt()).thenReturn(mockApiObject);
除了所有这些之外,还有一些方法可以使用Powermockito测试你的原始类,因为它没有改变但是这些并不理想,如果可能的话最好重构,这样你就可以使用普通的Mockito进行测试。这会给你很好的OO习惯。祝你好运!