【发布时间】:2017-04-20 17:47:59
【问题描述】:
我正在为以下课程编写单元测试
要测试的类:
public class RandomManager {
@Autowired
private ApplicationContext context;
@Autowired
private ClassA objectA;
public void methodToBeTested() {
objectA.methodToBeVerified(context.getBean(Random.class,"Yaswanth","Yaswanth"));
}
}
下面是测试类:
public class RandomManagerTest {
@Mock
private ClassA objectA;
@Mock
private ApplicationContext context;
@InjectMocks
private RandomManager randomManager;
@BeforeTest
public void before() {
MockitoAnnotations.initMocks(this);
doReturn(any(Random.class)).when(context)
.getBean(any(Class.class), any(), any());
}
@Test
public void methodToBeTestedTest() {
Random randomObject = new RandomObject("Yaswanth", "Yaswanth");
randomManager.methodToBeTested();
verify(objectA).methodToBeVerified(randomObject);
}
}
当我尝试存根时,上面的代码在之前的方法中失败了 applicationContext 模拟。我收到以下错误。
您不能在验证或存根之外使用参数匹配器。 正确使用参数匹配器的示例: when(mock.get(anyInt())).thenReturn(null); doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject()); 验证(模拟).someMethod(包含(“foo”))
如果最后一个消息可能会出现在 NullPointerException 之后 matcher 正在返回一个像 any() 但存根方法的对象 签名期望一个原始参数,在这种情况下,使用原始参数 备择方案。 何时(模拟.get(任何())); // 不好用,会提高 NPE 当(模拟.get(anyInt())); // 正确使用用法
此外,此错误可能会出现,因为您使用了参数匹配器 无法模拟的方法。以下方法不能 存根/验证:最终/私有/equals()/hashCode()。模拟方法 不支持在非公共父类上声明。
谁能帮我理解我在 上面的代码?
注意:我正在使用 TestNG 和 Mockito。我可以延长
AbstractTestNGSpringContextTests 并使用 spring-test.xml,声明我的
bean 和自动装配 applicationContext。我觉得这是一个矫枉过正
我的用例。我只需要模拟 applicationContext 的 getBean 方法。
【问题讨论】:
-
抱歉格式化。由于某些奇怪的原因,我无法提交问题。因此是丑陋的格式。
-
我真的不明白为什么你会在基于 Spring 的测试中模拟任何东西(除了可能使用 MockMVC 的 http 层)。当您使用
@RunWith(SpringJUnit4ClassRunner.class)时,您可以加载所有spring bean,它们将连接在一起,然后您测试实际代码,而不是返回测试中定义的东西的存根,并且永远不会实际执行依赖bean 中的代码。使用得当时 Mocking 是一个很棒的工具,但我从未将它用于基于 Spring 的测试,当我看到其他人这样做时,它总是一团糟。 -
我认为@KlausGroenbaek 是正确的。与其尝试模拟 Spring ApplicationContext,不如使用它。创建一个测试应用程序上下文,根据测试需要返回适当的 bean/mock。
-
@KlausGroenbaek
@RunWith不适用于 TestNG,而应使用AbstractTestNGSpringContextTests。 -
你说得对,我忘了是TestNG。我更喜欢 JUnit 和 Spring,因为它只是更好地集成。尽管在 TestNG 中有一些功能(例如参数化测试)更容易。两者之间存在范式差异,因为每个 JUnit 测试都在 Test 类的新实例上运行,其中 TestNG 为多个测试重用同一个实例,因此如果使用局部变量,则必须小心。
标签: java spring mockito testng