【问题标题】:Mockito how do I mock this method?Mockito 我如何模拟这个方法?
【发布时间】:2012-09-30 14:29:30
【问题描述】:

我是嘲笑的新手,所以我正在玩这个场景。我有一个方法MyClass.process() 调用MyClass.getFactory()。我想模拟 getFactory() 失败,以便我可以确保 process() 正确恢复。

似乎如果我在模拟之后调用getFactory(),它会正确抛出异常,但如果通过原始process() 方法调用,则不会抛出异常。

public class MyClass {

    public MyFactory getFactory() throws FactoryException {
        return ...
    }

    public String process() {
        try {
            MyFactory factory = getFactory();
            ...
        }
        catch(FactoryException ex) {
            ...
        }
    }

}

测试类:

public class MyClassTest {

    @Test
    public void testGetFactoryFails() {
        try {
            MyClass mockMyClass = mock(MyClass.class);
            when(mockMyClass.getFactory()).thenThrow(new FactoryException());
            mockMyClass.process();
            fail("FactoryException should have been thrown.");
        }
        catch(FactoryException ex) {
            // all good
        }
    }

}

感谢所有反馈。我可以看到在更复杂的环境下模拟单个方法会很快变得难以管理。 getFactory() 的内容并不重要,因为这是概念代码,而不是生产代码。

我尝试过的一种效果很好的方法:

public class MyClassTest {

    class MyClassMock1 extends MyClass {

        @Override
        public MyFactory getFactory() throws FactoryException {
            throw new FactoryException("Bad factory instance.");
        }

    }

    @Test
    public void testGetFactoryFails() {
        try {
            MyClassMock1 mockMyClass = new MyClassMock1();
            mockMyClass.process();
            fail("FactoryException should have been thrown.");
        }
        catch(FactoryException ex) {
            assertEquals("Bad factory instance.", ex.getMessage());
        }
    }

}

【问题讨论】:

  • 您正在模拟对象上调用 process 方法。使用 Mockito 时,您可以模拟要模拟的类的依赖项,而不是模拟类。
  • 你能解释一下这是什么意思吗?
  • 能否把getFactory的内容贴出来,让我看看它在什么情况下会抛出异常,以便我解释一下?

标签: java unit-testing junit mocking


【解决方案1】:

我将扩展 @Can't Tell 已经说过的内容。您使用模拟库来模拟被测类的依赖关系。在您的情况下,您测试 MyClass 并且在测试期间您应该模拟所有依赖项(MyClass 使用的类)。

您想在一个类中模拟一个方法并测试另一个方法。虽然这在技术上可能是可行的(但由于各种代理/包装机制对您不起作用),但它肯定是一个糟糕的设计。

向我们展示您的getFactory() 方法。如果它单独处理整个工作,请将其提取到单独的类并模拟它。如果它只委托给另一个类,则模拟该类。可悲的是,这个提取的类将被命名为...MyFactoryFactory...

一旦你提取了你的依赖,在测试之前模拟它并传递给MyClass(通过构造函数、设置器......)

【讨论】:

    【解决方案2】:

    这是因为部分模拟是不好的(这就是你想要做的)。它恰恰导致了这类问题。它主要用于遗留系统测试。如果您编写新代码并且必须使用部分模拟,这意味着您很可能有糟糕的系统设计。

    您应该让getFactory 将调用委托给其他一些服务(注入到MyClass),然后您应该模拟整个服务

    【讨论】:

      猜你喜欢
      • 2020-12-08
      • 1970-01-01
      • 1970-01-01
      • 2020-03-20
      • 2011-01-17
      • 1970-01-01
      相关资源
      最近更新 更多