模拟ColumnDefinitions.Definition确实返回mock,但在测试代码中的行为类似于null

时间:2016-05-06 22:38:11

标签: java unit-testing cassandra mocking mockito

我有以下代码准备模拟以使用Cassandra测试我的服务(我需要模拟com.datastax.driver.core.ColumnDefinitions.Definition):

@RunWith(PowerMockRunner.class)
public class TestMyClass{
private MyClass target;
  @Before
  public void setUp() throws Exception {
    ColumnDefinitions mockColumnDefinitions=Mockito.mock(ColumnDefinitions.class);
    Mockito.when(mockRow.getColumnDefinitions()).thenReturn(mockColumnDefinitions);
    target= new MyClass();
    Definition mockDef = Mockito.mock(Definition.class);
    List<Definition> defList = new ArrayList<Definition>();
    defList.add(mockDef);
    Iterator mockIterator = Mockito.mock(Iterator.class);
    Mockito.when(mockColumnDefinitions.iterator()).thenReturn(mockIterator);
    Mockito.when(mockIterator.hasNext()).thenReturn(true, false);
    Mockito.when(mockIterator.next()).thenReturn(mockDef);
    Mockito.when(mockDef.getName()).thenReturn(NAME);
  }
 @Test
 public void testMyMethod() throws Exception {
    target.MyMethod();
 }
}

测试执行在这个地方很顺利,我在不同的地方有这种类型的代码,所以它应该工作。 在我正在测试的服务中,我有以下代码:

ColumnDefinitions colDef = row.getColumnDefinitions();
Iterator<Definition> defIterator = colDef.iterator();
while (defIterator.hasNext()) {
    Definition def = defIterator.next();
    String columnName = def.getName();
}

当我调试此代码时,我看到colDefdefIterator都已成功模拟。我在调试变量区看到类似的东西:

Mock for Iterator, hashCode: 430126690

但是在defIterator.next()调用之后我看到虽然def是一个对象而不是null,但它并不像Iterator那样显示哈希码,而是我看到了:

com.sun.jdi.InvocationException occurred invoking method.

调用此字符串后:

String columnName = def.getName();

如果def为null,我会立即得到NullPointerException。 我究竟做错了什么? 感谢。

编辑1 ________________________________________________________________________

我也尝试使用相同的方法使用PowerMockito,结果是相同的。

编辑2 ________________________________________________________________________

我添加了整个测试方法代码。

1 个答案:

答案 0 :(得分:2)

这个问题创建已经有一段时间了。我几天前遇到过同样的问题,我已经用以下方式解决了这个问题(我希望我提出的解决方案可以帮助将来的某个人):

首先,我想澄清ColumnDefinition.Definition类是一个public static嵌套类,它有四个private final字段,只有一个构造函数:Definition (String keyspace, String table, String name and DataType type)(更多信息)详情请参阅ColumnDefinitions.Definition javadocColumnDefinitions source code)。因此,MockitoPowermock无法模拟此嵌套类,因为其final字段。

<强> SOLUTION:

我必须使用反射创建一个真实对象,而不是一个类ColumnDefinition.Definition的模拟对象,因此您可以按如下方式初始化mockDef对象:

Constructor<Definition> constructor = (Constructor<Definition>) Definition.class.getDeclaredConstructors()[0]; // as Definition only has one constructor, 0 will be passed as index
constructor.setAccessible(true);
Definition mockDef = constructor.newInstance("keyspace", "table", "name", null);

替换代码段中的以下代码:

Definition mockDef = Mockito.mock(Definition.class);

然后在执行这行代码时永远不会再抛出NullPointerException:

String columnName = def.getName();