【问题标题】:Mock final private variable using Mockito/Powermock framework使用 Mockito/Powermock 框架模拟最终私有变量
【发布时间】:2013-10-02 17:40:20
【问题描述】:

我正在尝试模拟如下所示的类

public class MessageContainer {
  private final MessageChain[] messages;


  MessageContainer(final int numOfMessages, final MessageManagerImpl manager, final Object someOtherStuff) {
    messages = new MessageChain[numOfMessages]
    // do other stuff
  }

  public void foo(final int index) {
    // do something
    messages[index] = getActiveMessage();
  }
}

我的测试代码如下:

@Test
public void testFoo() {
  MessageContainer messageContainer = Mockito.mock(MessageContainer.class);
  Mockito.doCallRealMethod().when(messageContainer).foo(anyIndex);
}

我收到了 NullPointerException,因为 'messages' 为空。我尝试使用@InjectMocks 注入模拟,但是不支持这种情况,因为并非构造函数的每个参数都被声明为成员。

我还尝试使用 WhiteBox 设置“消息”字段

    Whitebox.setInternalState(messageContainer, MessageChain[].class, PowerMockito.mock(MessageChain[].class));

但我得到一个编译错误,因为 setInternalState 只支持 (Object, Object, Object) 而不是 Object[]。

有没有办法模拟一个私有的 final 字段?

提前谢谢你们。

【问题讨论】:

  • MessageChain 的构造函数无法编译...您是否遗漏了 varargs 参数?一种或另一种方式,它有一个错字。一旦改正,我想我可以帮助你。
  • 你是在模拟MessageContainer,还是在尝试用模拟的MessageChain 构造一个真实的MessageContainer?您的问题不清楚。
  • @TJamesBoone:是的,我忽略了 MessageContainer 的其他参数。我只是做了一个例子来展示我想要做什么。
  • @TomG:我正在尝试模拟 MessageContainer。我刚刚更新了我的问题,希望现在更清楚。谢谢你:)
  • 来自fooNullPointerException 应该是不可能的。您没有调用foo 的真正实现,因为您有一个MessageContainer 的模拟实例。请展示整个测试类。

标签: java mockito


【解决方案1】:

根据您的编辑和 cmets,我会说模拟这个类并验证方法被调用就足够了。

如果是第三方代码,您应该依赖其方法签名,该方法签名包含类的公共 API。否则,您将测试与您无法控制的事物紧密耦合。当他们决定使用 Collection 而不是数组时,你会怎么做?

简单写:

MessageContainer container = mock(MessageContainer.class);
//Your code here...
verify(container).foo(obj);

【讨论】:

  • 不过,我还有一个问题。如果我的单元计算 foo 的参数,在这种情况下是“索引”,我无法访问它以传递给 foo()。我会写:“验证(容器).foo(anyInt)吗?”。如果我想测试索引是否创建正确怎么办?示例:MyUnit unitUnderTest = new MyUnit(); unitUnderTest.createMessage(); // 在此方法中创建索引并调用 foo() MessageContainer container = mock(MessageContainer.class); verify(container).foo(anyInt());// 如何测试是否创建了正确的索引?
  • 如果您知道MyUnit 类应该创建什么索引,您可以在verify 调用中使用该编号而不是anyInt() 匹配器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-22
相关资源
最近更新 更多