【问题标题】:Mocking ColumnDefinitions.Definition does return mock, but is behaves like null in the tested code模拟 ColumnDefinitions.Definition 确实返回模拟,但在测试代码中的行为类似于 null
【发布时间】:2016-05-06 22:38:10
【问题描述】:

我有以下代码准备模拟以使用 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 是一个对象而不是空值,但它不像Iterator 那样显示哈希码,而是我看到了这个:

com.sun.jdi.InvocationException occurred invoking method.

在调用这个字符串之后:

String columnName = def.getName();

我立即得到NullPointerException,就像 def 为空一样。 我究竟做错了什么? 谢谢。

编辑 1 ________________________________________________________________________

我也试过用PowerMockito 用同样的方法代替,结果是一样的。

编辑 2 ________________________________________________________________________

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

【问题讨论】:

  • 你能复制粘贴完整的测试方法吗?
  • @doanduyhai 请检查,我添加了周围的内容。

标签: java unit-testing cassandra mocking mockito


【解决方案1】:

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

首先,我想澄清一下ColumnDefinition.Definition类是一个public static嵌套类,它有四个private final字段并且只有一个构造函数:Definition (String keyspace, String table, String name and DataType type)(更多细节请参考ColumnDefinitions.Definition javadocColumnDefinitions source code)。因此这个嵌套类不能被MockitoPowermock 模拟,因为它有final 字段。

解决方案:

我必须创建一个真实的对象,而不是使用反射模拟的 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);

在你的 sn-p 中替换这行代码:

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

那么在执行这行代码的时候就不会再抛出NullPointerException了:

String columnName = def.getName();

【讨论】:

    猜你喜欢
    • 2021-08-02
    • 2020-12-16
    • 1970-01-01
    • 2018-09-12
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 2022-01-11
    • 1970-01-01
    相关资源
    最近更新 更多