7

我想使用 Mockito 对抽象类进行单元测试,如this great answer中所述。

诀窍是,抽象类依赖于注入其构造函数的策略。我已经创建了该策略的模拟,并且我希望我的 BaseClass 模拟实例将模拟策略用于我的单元测试。

关于如何连接它的任何建议?我目前没有使用任何 IoC 框架,但正在考虑使用 Spring。也许它会成功?

// abstract class to be tested w/ mock instance
abstract BaseClass
{
    // Strategy gets mocked too 
    protected BaseClass( Strategy strategy)
    {
        ...
    }
}

更新
根据 Mockito 邮件列表,目前没有办法将参数传递给模拟的构造函数。

4

3 回答 3

6

我最终只是使用反射在我的基类中设置了一个私有字段,如下所示:

// mock the strategy dependency
Strategy strategyMock = mock( Strategy.class);
when(....).thenReturn(...);

// mock the abstract base class
BaseClass baseMock = mock(BaseClass.class, CALLS_REAL_METHODS);

// get the private streategy field
Field strategyField = baseMock.getClass().getSuperclass().getDeclaredField("_privateStrategy");

// make remove final modifier and make field accessible
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(strategyField, strategyField.getModifiers() & ~Modifier.FINAL);          
strategyField.setAccessible(true);

// set the strategy
strategyField.set(baseMock, strategyMock);

// do unit tests with baseMock
...

如果私有字段的名称发生变化,它会中断,但它会被评论,我可以忍受。很简单,它是一行代码,我发现这比公开任何设置器或必须在我的测试中显式地继承子类更可取。

编辑: 所以它不再是一行代码,因为我的私有字段需要是“最终的”,需要一些额外的反射代码才能解决。

于 2012-04-17T16:16:43.730 回答
5

我已经看到在春季上下文级别使用 Mockito 完成了这种事情。

例如:

<bean id="myStrategy" name="myStrategy" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="Strategy" />
</bean>

我希望这会有所帮助。

于 2012-04-16T22:15:45.640 回答
0

你不需要做任何特别的事情。像往常一样模拟 bean:

Bean bean = mock(Bean.class); 
when(bean.process()).thenReturn(somethingThatShouldBeNamedVO);

只是工作:)

于 2012-04-17T12:30:03.730 回答