模拟假定存在的私有变量

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

在我正在编写一些unit testing的类中,我遇到了一个我尚未遇到/解决过的场景。 我有一个JMS资源( QueueConnectionFactory供参考,但它没关系),这是我正在测试的类的私有变量。 由于它具有javax.annotation.Resource注释,因此在运行时它被认为是可用的。 在测试期间,它不是,这就需要模拟这个对象。

它不是一个静态类,并没有以静态方式使用,如果它是我可以轻松地使用我遇到的各种静态模拟方法进行模拟。 由于资源永远不会在本地创建(在构造函数中或甚至在测试构造函数中),因此我无法传入Mock对象,因此在测试的运行时,使用mock而不是实际对象。 如何模拟此资源,以便在测试执行时,它将用于代替我正在测试的类中的私有@Resource对象?

作为参考,代码在QueueConnectionFactory上调用createConnection() ,因为Factory尚未初始化/ QueueConnectionFactory ,所以它会抛出空指针exception。

 @Stateless public class Example{ @Resource(name = "jms/exampleQCF") private QueueConnectionFactory queueFactory; ... public void testMe(){ Connection connection = queueFactory.createConnection(); ... } } 

经过更多的狩猎并查看Mockito / Powermock提供的所有选项之后,我找到了解决方案(如果其他人遇到同样的问题我会分享)。

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

  1. 在测试类中为要测试的类添加变量,并为其提供注释@InjectMocks (org.Mockito.InjectMocks)。
  2. 使用@Mock注释设置要注入的模拟。 使用@Mock (name = "privateVariableNameHere") name属性将Mock对象映射到您正在测试的类中的私有变量。
  3. 无论是在设置function中还是在调用类之前,都要初始化模拟。 我发现最简单的方法是使用带有@Before注释的“setup”方法。 然后在里面调用MockitoAnnotations.initMocks(this); 使用@Mock注释快速初始化任何内容。
  4. 在测试方法中定义Mockfunction(在调用您正在测试的方法之前)。
  5. 使用@InjectMock对象,调用您正在测试的方法……应该按照前面步骤中的定义连接@InjectMock并运行。

因此,对于我上面使用的示例类,test / mock的代码将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(); } }