我正在测试一个类“DataSource”,它扩展了另一个类“ExtendedDataSource”。我在“DataSource”类中测试的方法正在调用“ExtendedDataSource”类中的另一个受保护方法。
class DataSource extends ExtendedDataSource {
@Override
protected Connection setup(Properties props) {
Connection connection = super.getConnection(props);
return connection;
}
}
class ExtendedDataSource extends AbstractSource {
@Override
protected Connection getConnection(Properties props) {
// here an user is retrieved from an abstract class that this class inherits
// In this line I am getting an exception IllegalStateException--"user not set"
String user = getUser();
// Does something with props
// Calls another protected method with the props as argument
anothermethod(props);
}
protected anothermethod(Properties props){
//call another method that will do something with props
}
}
public abstract class AbstractSource extends AnotherAbstractClass{
public String getUser() {
//the user as string
return user;
}
}
DataSource类的测试如下:-
public class DataSourceTest {
@InjectMocks
DataSource dataSource;
@Mock
properties props;
@Test
public void datatest() {
DataSource dataSource = new DataSource();
dataSource.getConnection(props);
}
}
我该如何克服这种情况?我还应该模拟 Abstract 类吗?但这样我就得把所有的课都mock掉吗?
如果您正在测试
DataSource
类,则不应该嘲笑它。通常你会模拟类的依赖关系。目的是通过注入其依赖项的模拟,将要测试的类引入某些 state,然后在给定提供的 state 的情况下断言其方法的返回值。例如,如果 DataSource
的构造函数如下所示:
public DataSource(Object o) {
this.o = o;
}
然后你应该模拟
o
,然后用这个模拟的 DataSource
创建一个 o
的实例。鉴于您嘲笑的状态,测试现在正在调用dataSource.setup(...)
:
Object mock = Mockito.mock(Object.class);
DataSource dataSource = new DataSource(mock);
Assert.assertNotNull(dataSource.setup(...));
现在来看你的案例 - 你所描述的问题正是为什么在可能的情况下我更喜欢组合而不是继承。我的建议是
DataSource
将在其构造函数中获得 ExtendedDataSource
(考虑重命名它)而不是扩展它:
public DataSource(ExtendedDataSource extendedDataSource) {
this.extendedDataSource = extendedDataSource;
}
现在您可以模拟
ExtendedDataSource
并为 ExtendedDataSource.getConnection
设置一些返回值,然后创建 DataSource
的实例并在构造函数中传递模拟,并根据需要断言 DataSource
的行为。