【问题标题】:How do I mock Spring ApplicationContext's getBean method using Mockito for writing unit tests with TestNG?如何使用 Mockito 模拟 Spring ApplicationContext 的 getBean 方法以使用 TestNG 编写单元测试?
【发布时间】: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


【解决方案1】:

问题来自doReturn(any(Random.class)),您不能使用any()。 只需将其替换为真实实例即可。

【讨论】:

  • 谢谢@juherr。有效。但是为什么我们不应该在 doReturn() 中使用 any() 呢?
  • 我想是因为任何* id 用于参数匹配,而不是返回的参数。实际上,解决方案在错误消息中。但也许你想要的可能是可能的(一个很好的新问题)
猜你喜欢
  • 2021-12-02
  • 1970-01-01
  • 2020-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多