【发布时间】:2016-05-25 15:00:40
【问题描述】:
我对 mockito 并不陌生,但这次我在工作中发现了一个有趣的案例。我希望你能帮我解决这个问题。
我需要注入 mock 以在测试期间更改某些方法行为。问题是,bean 结构是嵌套的,并且这个 bean 在其他 bean 中,无法从测试方法访问。我的代码如下所示:
@Component
class TestedService {
@Autowired
NestedService nestedService;
}
@Component
class NestedService {
@Autowired
MoreNestedService moreNestedService;
}
@Component
class MoreNestedService {
@Autowired
NestedDao nestedDao;
}
@Component
class NestedDao {
public int method(){
//typical dao method, details omitted
};
}
所以在我的测试中,我希望调用 NestedDao.method 返回模拟答案。
class Test {
@Mock
NestedDao nestedDao;
@InjectMocks
TestedService testedSevice;
@Test
void test() {
Mockito.when(nestedDao.method()).thenReturn(1);
//data preparation omitted
testedSevice.callNestedServiceThatCallsNestedDaoMethod();
//assertions omitted
}
}
我已经尝试做一个 initMocks:
@BeforeMethod
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
还要在我的测试类上添加注释:
@RunWith(MockitoJUnitRunner.class)
总是从方法中得到空指针或错误答案(未模拟)。
我猜是这个嵌套调用错误,使得无法模拟这个 Dao。 我还读到@InjectMocks 仅适用于 setter 或构造函数注入,我缺少这些(只是私有字段上的 @Autowire),但当我尝试时它没有工作。
猜猜我错过了什么? ;)
【问题讨论】:
-
你不是在模拟嵌套服务,那么它应该如何工作?并且通常不模拟nestedDao,而是调用
when(nestedService.callDaoMethod()).return("stuff which the dao should return")。 -
好的,我怎样才能模拟嵌套服务,然后模拟嵌套在其中的东西,然后再次相同?在互联网上没有这样做的例子。我看到的另一种方法是使用构造函数并创建对象,但是依赖项对我来说太复杂了(我是项目中的新手)。如果我能告诉 NestedDao 类必须像往常一样返回另一个对象,那就太好了。这个调用在层次结构中很深,所以很难模拟所有嵌套的服务。
-
“然后模拟嵌套在其中的东西,然后再次相同” 没有理由这样做。这是一个单元测试。您正在测试
TestedService而不是NestedService及其嵌套依赖项的实现细节。例如你的班级MoreNestedService...这个班级甚至不需要在测试中提及。您只模拟TestedService并告诉该模拟在某个方法调用上返回什么。这个方法可能在“现实生活”中调用嵌套方法现在并不重要。 -
顺便说一句:请创建一个minimal reproducible example。你的课程已经没问题了,但是在不知道你正在测试、测试数据是什么以及你断言什么的情况下,很难告诉你问题出在哪里。您仍然可以使用抽象数据和类名,但该示例应该重现您当前的问题。
-
好的,等我有空的时候我会做的:)谢谢你到目前为止的帮助。
标签: java spring junit dependency-injection mockito