我是嘲笑的新手,所以我正在玩这个场景。我有一个调用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());
}
}
}
答案 0 :(得分:1)
我会扩展@Can't Tell已经说过的内容。您可以使用模拟库来模拟被测试类的依赖关系。在您的情况下,您测试MyClass
并且在测试期间您应该模拟所有依赖项(MyClass
使用的类)。
您想在一个类中模拟单个方法并测试另一个方法。虽然这在技术上可能是可行的(但由于各种代理/包装机制对你来说并不适合),但这肯定是一个糟糕的设计。
向我们展示您的getFactory()
方法。如果它单独处理整个工作,将其提取到一个单独的类并进行模拟。如果它只委托给另一个类,那就嘲笑那个。遗憾的是,这个提取的类将被命名为...... MyFactoryFactory
...
一旦你提取了你的依赖项,在测试之前模拟它并传递给MyClass
(通过contstructor,setter ......)
答案 1 :(得分:0)
这是因为部分嘲笑是不好的(这就是你想要做的)。它完全导致了那些问题。它主要用于遗留系统测试。如果你编写新的代码而你必须使用部分模拟,这意味着你很可能有糟糕的系统设计。
你应该让getFactory
将调用委托给其他服务(注入MyClass
),然后你应该模拟整个服务