【发布时间】:2015-07-23 12:43:58
【问题描述】:
我正在尝试测试一个使用计算器类和一些静态方法的类。我已经以类似的方式成功地模拟了另一个班级,但事实证明这个班级更加顽固。
似乎如果模拟方法包含对传入参数之一的方法调用,则静态方法不会被模拟(并且测试中断)。删除内部调用显然不是一种选择。我这里有什么明显的遗漏吗?
这是一个精简版本,其行为方式相同......
public class SmallCalculator {
public static int getLength(String string){
int length = 0;
//length = string.length(); // Uncomment this line and the mocking no longer works...
return length;
}
}
这是测试...
import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.solveit.aps.transport.model.impl.SmallCalculator;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ SmallCalculator.class})
public class SmallTester {
@Test
public void smallTest(){
PowerMockito.spy(SmallCalculator.class);
given(SmallCalculator.getLength(any(String.class))).willReturn(5);
assertEquals(5, SmallCalculator.getLength(""));
}
}
这个问题似乎有些混乱,所以我设计了一个更“现实”的例子。这增加了一层间接性,因此看起来我没有直接测试模拟方法。 SmallCalculator 类没有改变:
public class BigCalculator {
public int getLength(){
int length = SmallCalculator.getLength("random string");
// ... other logic
return length;
}
public static void main(String... args){
new BigCalculator();
}
}
这是新的测试类...
import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.solveit.aps.transport.model.impl.BigCalculator;
import com.solveit.aps.transport.model.impl.SmallCalculator;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ SmallCalculator.class})
public class BigTester {
@Test
public void bigTest(){
PowerMockito.spy(SmallCalculator.class);
given(SmallCalculator.getLength(any(String.class))).willReturn(5);
BigCalculator bigCalculator = new BigCalculator();
assertEquals(5, bigCalculator.getLength());
}
}
【问题讨论】:
-
除非这段代码/测试只是为了证明模拟框架无法模拟它应该模拟的东西的概念,否则这里会有很大的混乱。应该不模拟正在测试的类,而是模拟它的依赖项,以便她可以测试类的行为。
-
在这个例子中,当 string.length() 被调用时,我得到一个 NPE。这很奇怪,因为似乎参数被替换了,但实际方法并没有被嘲笑。
-
@Alp 如前所述,原始测试试图模拟一个从实际测试类中调用的类。这个例子只是为了显示失败。
标签: java unit-testing powermockito