使用JMockit 1.1,我想做的就是调用私有方法并测试返回值。但是,我无法从JMockit De-Encapsulation示例中了解如何执行此操作。
我试图测试的方法是这个类中的私有方法:
public class StringToTransaction {
private List<String> parseTransactionString(final String input) {
// .. processing
return resultList;
}
}
我的测试代码如下。
@Test
public void testParsingForCommas() {
final StringToTransaction tested = new StringToTransaction();
final List<String> expected = new ArrayList<String>();
// Add expected strings list here..
new Expectations() {
{
invoke(tested, "parseTransactionString", "blah blah");
returns(expected);
}
};
}
我得到的错误是:
java.lang.IllegalStateException:缺少对模拟类型的调用 这点;请确保此类调用仅在此之后出现 声明合适的模拟字段或参数
也许我在这里误解了整个API,因为我认为我不想模拟这个类..只是测试调用私有方法的结果。
答案 0 :(得分:33)
我认为你这太复杂了。您根本不应该使用Expectations块。你需要做的就是这样:
@Test
public void testParsingForCommas() {
StringToTransaction tested = new StringToTransaction();
List<String> expected = new ArrayList<String>();
// Add expected strings list here..
List<String> actual = Deencapsulation.invoke(tested, "parseTransactionString", "blah blah");
assertEquals(expected, actual);
}
基本上,通过Deencapsulation调用私有方法并测试实际值是否等于预期值。就像你公开的方法一样。没有嘲弄,所以不需要Expectations阻止。
答案 1 :(得分:3)
此时,我不知道是否可以或应该使用JMockit。测试我的私有方法可以使用普通的旧反射来完成,尽管我开始本练习以了解JMockit(并测试我的代码)。如果JMockit不能用于此,那么我可以使用反射。
@Test
public void testParsingForCommas() throws Exception {
StringToTransaction tested = new StringToTransaction();
ArrayList<String> expected = new ArrayList<>();
expected.add("Test");
Method declaredMethod =
tested.getClass().getDeclaredMethod("parseTransactionString",
String.class);
declaredMethod.setAccessible(true);
Object actual = declaredMethod.invoke(tested, "blah blah");
assertEquals(expected, actual);
}
此处对setAccessible(true)
的调用很重要,或者在调用私有方法时invoke
会爆炸。
declaredMethod.setAccessible(true);
但你想知道什么是真的很酷?如果你不打电话给setAccessible(true)
,它会被java.lang.StackOverflowError
炸掉! :)
答案 2 :(得分:1)
因为在最新的 Jmockit 中不允许模拟私有方法。可以模拟该私有方法中使用的 API 作为解决方法,而不是模拟私有方法。
此变通方法也可以视为最终解决方案。
示例:
实际班级:
class A {
private int getId(String name){ //private method
return DAOManager.getDao().getId(name); //Call to non-private method can be mocked.
}
}
测试类:
public class ATest{
@Before
public void setUp(){
new MockDAOManager();
}
//Mock APIs used by the private method `getId`.
public static class MockDAOManager extends MockUp<MockDAOManager>{
static mocked_user_id = 101;
@Mock
public DAOManager getDao() throws Exception{
return new DAOManager();
}
@Mock
public Integer getId(String name){
return mocked_user_id;
}
}
}
注意:
DAOManager.getDao().getId(name)
不是私有 API。答案 3 :(得分:0)
从1.35(?)开始,jmockit删除了该辅助方法。由于它不再有用(我不太了解)的原因
但是,可以在其他地方使用此实用程序
org.springframework.test.util.ReflectionTestUtils
答案 4 :(得分:0)
如@Jeff Olson所述,您还可以通过声明@Tested
来调用bean的私有方法。
这是一个示例:
```java
@Tested
private YourServiceImplClass serviceImpl;
@Test
public void testPrivateMethod() {
List<String> expected = new ArrayList<String>();
// Add expected strings list here..
List<String> actual = Deencapsulation.invoke(serviceImpl, "yourPrivateMethod", "arguments");
assertEquals(expected, actual);
}
```
答案 5 :(得分:-1)
为什么要直接测试私有方法?大多数情况下,API方法即公共接口方法都是单元测试的,因为私有方法也将被间接测试以及它们。您可以将断言语句与来自私有方法的期望值放在公共方法中。因此,如果断言失败,您确定私有方法存在一些问题。所以你不需要单独测试它。