2016-01-25 98 views
2

是否可以模拟抽象类并使用Mockito注释将其注入模拟类。我现在有以下情况:嘲笑抽象类并使用Mockito注释注入类?

@Mock private MockClassA mockClassA; 
@Mock private MockClassB mockClassB; 

@Mock(answer = Answers.CALLS_REAL_METHODS) private AbstractClassUnderTest abstractClassUnderTest; 

@Before 
public void init() { 
    MockitoAnnotations.initMocks(this); 
    Whitebox.setInternalState(abstractClassUnderTest, mockClassA); 
    Whitebox.setInternalState(abstractClassUnderTest, mockClassB); 
} 

我想使用类似的AbstractClassUnderTest @InjectMocks但不能与@Mock组合使用。目前的情况,使用Powermock的Whitebox,可行,但我很好奇,如果可以用注释解决它。我找不到任何解决方案或例子。

(我知道反对测试抽象类和我个人,而测试的具体实施,只是使用@InjectMocks。)

回答

4

我不知道有任何的方式去这一点,一个清晰理由:@InjectMocks适用于被测试的非模拟系统,而@Mock适用于模拟协作者,Mockito不适用于任何类在同一测试中填充这两个角色。

请注意,您的@Mock(CALLS_REAL_METHODS)声明为inherently dangerous:您正在测试AbstractClassUnderTest,但未运行任何构造函数或初始化任何字段。我不认为你可以期望这个设计的测试是现实的或强健的,无论注释能够或不能为你做什么。 (就我个人而言,我以前赞成真正的抽象类的部分模仿作为“工具箱中的工具”,但是我现在认为它们离现实太远以至于无法使用。)

我在你的位置,我会创建一个用于测试的小覆盖的实现:

@RunWith(JUnit4.class) public class AbstractClassTest { 
    /** Minimial AbstractClass implementation for testing. */ 
    public static class SimpleConcreteClass extends AbstractClass { 
    public SimpleConcreteClass() { super("foo", "bar", 42); } 
    @Override public void abstractMethod1() {} 
    @Override public String abstractMethod2(int parameter) { return ""; } 
    } 

    @InjectMocks SimpleConcreteClass classUnderTest; 
    @Mock mockClassA; 
    @Mock mockClassB; 
} 

在这一点上,你有一个简单的和可预见的抽象类实现,如果你只是想测试你甚至可以使用不带模拟框架该AbstractClass具有与之前相同的扩展API。 (这是抽象类经常被忽视的测试。)你甚至可以提取它,因为它可能对其他测试有用:如果你想覆盖单个测试类的抽象行为,你可以创建一个匿名内部类只需一个方法覆盖,或者您可以设置classUnderTest = spy(classUnderTest);来设置Mockito代理和您想要的行为。

(记住,@InjectMocks和@Spy不能可靠一起使用,如与它连接this GitHub issue与谷歌代码和邮件列表线程记录。)