java - 模拟假定存在的私有(private)变量

标签 java mocking mockito powermock

如果模拟对象没有在您正在测试的类中创建/初始化,它不是静态的(单例模式),或者您没有某种测试构造函数可以 Hook ,那么您如何在运行时获取模拟对象?

在我正在为其编写一些单元测试的类(class)中,我遇到了一个我尚未遇到/解决的场景。我有一个 JMS 资源(一个 QueueConnectionFactory 供引用,但它应该无关紧要),它是我正在测试的类的私有(private)变量。因为它有 javax.annotation.Resource 注释,所以在运行时假定它是可用的。在测试期间,它不是,这就需要模拟这个对象。

它不是静态类,也没有以静态方式使用,如果是的话,我可以很容易地使用我遇到的各种静态模拟方法进行模拟。由于资源从未在本地创建(在构造函数中甚至在测试构造函数中),我无法传入 Mock 对象,以便在测试运行时使用模拟对象而不是实际对象。我怎样才能模拟这个资源,以便在测试执行时,它将用于代替我正在测试的类中的私有(private) @Resource 对象?

作为引用,代码正在 QueueConnectionFactory 上调用 createConnection(),由于工厂尚未初始化/模拟,该代码会抛出空指针异常。

@Stateless
public class Example{
  @Resource(name = "jms/exampleQCF")
  private QueueConnectionFactory queueFactory;

  ...

  public void testMe(){
    Connection connection = queueFactory.createConnection();
    ...
  }
}

最佳答案

在四处寻找并查看 Mockito/Powermock 必须提供的所有选项后,我找到了解决方案(我会分享它以防其他人遇到同样的问题)。

当您拥有从未初始化的私有(private)成员变量(并且只是假设在其他地方创建)时,您可以使用 @InjectMocks 注释将您想要的模拟“注入(inject)”到您正在测试的类中.

  1. 在您的测试类中为您正在测试的类添加一个变量,并为其提供注释 @InjectMocks (org.Mockito.InjectMocks)。
  2. 使用@Mock 注释来设置您要注入(inject)的模拟。使用 @Mock (name = "privateVariableNameHere") name 属性将 Mock 对象映射到您正在测试的类中的私有(private)变量。
  3. 在设置函数中或在调用类之前,初始化模拟。我发现的最简单的方法是使用带有 @Before 注释的“setup”方法。然后在里面调用 MockitoAnnotations.initMocks(this); 以使用 @Mock 注释快速初始化任何东西。
  4. 在测试方法中定义 Mock 功能(在调用您正在测试的方法之前)。
  5. 使用 @InjectMock 对象,调用您正在测试的方法...应该挂接模拟并按照前面步骤中的定义工作。

因此对于我在上面使用的示例类,测试/模拟的代码会将 Connection 作为模拟返回,您可以用它做任何事情。根据我问题中的上述示例,代码如下所示:

@RunWith(PowerMockRunner.class)
@PrepareForTest({/* Static Classes I am Mocking */})
public class ExampleTest {
  @Mock (name = "queueFactory") //same name as private var.
  QueueConnectionFactory queueFactoryMock;
  @Mock
  Connection connectionMock; //the object we want returned
  @InjectMocks
  Example exampleTester; //the class to test

  @Before
  public void setup(){
    MockitoAnnotations.initMocks(this); // initialize all the @Mock objects
    // Setup other Static Mocks
  }

  @Test
  public void testTestMe(){
    //Mock your objects like other "normally" mocked objects
    PowerMockito.when(queueFactoryMock.createConnection()).thenReturn(connectionMock);
    //...Mock ConnectionMock functionality...
    exampleTester.testMe();
  }
}

关于java - 模拟假定存在的私有(private)变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19521220/

相关文章:

java - 使用 Eclipse 从 Android 中的 C 代码调用 Java 函数,而不调用 Java

python - Mock 的 autospec 将错误的参数注入(inject)到被调用的函数中

java - 如何为 Integer.class 编写匹配器

java - Mockito.when 是如何在后台工作的

java - 获取任意java方法的委托(delegate)函数

java - 在指定日期之前在 Android 中通知

java - 如何处理maven下载的api中缺少的ExpressionFactory#newInstance()方法?

reactjs - jest 中的 jest.fn() 和 jest.spyOn() 方法有什么区别?

c++ - Hippo Mocks 中具有不同返回值的多个预期调用是否可以重复使用模拟?

java - 用逗号作为小数点分隔符来解析Double的最佳方法?