我试图使用Mockito Framework 1.9.5和JUnit 4.11来模拟我的GenericDao对象,但是Mockito总是模拟第一个与该类型匹配的字段.同样符合名称也无济于事.
如API(http://docs.mockito.googlecode.com/hg-history/58d750bb5b94b6e5a554190315811f746b67f578/1.9.5/org/mockito/InjectMocks.html)中所述,Mockito应评估正确的字段以进行模拟.
预期产量:
EmployeeService.absenceDao -> null
EmployeeService.creditDao -> null
EmployeeService.employeeDao -> Mocked object
有效输出:
EmployeeService.absenceDao -> Mocked object
EmployeeService.creditDao -> null
EmployeeService.employeeDao -> nulll
重现情况的代码:
@RunWith(MockitoJUnitRunner.class)
public class EmployeeServiceTest {
@InjectMocks
EmployeeService employeeService;
@Mock(name = "employeeDao")
GenericDao<Employee> employeeDao;
@Test
public void testFindEmployeeByUsername() {
// some tests
}
}
我的模拟类,包含几个GenericDao字段,但我只是想模拟employeeDao:
@Service
@Transactional
public class EmployeeService {
@Autowired
private GenericDao<Employee> employeeDao;
@Autowired
private GenericDao<Credit> creditDao;
@Autowired
private GenericDao<Absence> absenceDao;
解决方法:
根据我调试的内容,看起来Mockito无法通过注释处理类型参数.如果您遵循MockitoJunitRunner的堆栈跟踪,您最终会进入下面的DefaultAnnotationEngine是您要查看的方法.
public void process(Class<?> clazz, Object testInstance) {
Field[] fields = clazz.getDeclaredFields(); //This is the line of concern
for (Field field : fields) {
boolean alreadyAssigned = false;
for(Annotation annotation : field.getAnnotations()) {
Object mock = createMockFor(annotation, field);
if (mock != null) {
throwIfAlreadyAssigned(field, alreadyAssigned);
alreadyAssigned = true;
try {
new FieldSetter(testInstance, field).set(mock);
} catch (Exception e) {
throw new MockitoException("Problems setting field " + field.getName() + " annotated with "
+ annotation, e);
}
}
}
}
我评论的那一行在没有type参数的情况下拉回你的GenericDao.那么当它注入它时.现在它并不重要,因为你通常会嘲笑Object,无论如何控制返回的内容.但是在你的情况下,你有3个dao,这意味着当你对你的employeeDao进行调用并且模拟在AbsenceDao上时它将抛出NullPointerException.我确实做了尝试:).但如果你嘲笑这三个人.它过去了.现在我担心它实际上调用了正确的方法,所以我写了一些验证案例以确保.以下是我的所作所为.
GenericDAO
public interface GenericDao<T>
{
public T getObject();
}
的EmployeeService
@Service
@Transactional
public class EmployeeService
{
@Autowired
private GenericDao<Absence> absenceDao;
@Autowired
private GenericDao<Credit> creditDao;
@Autowired
private GenericDao<Employee> employeeDao;
public Absence getAbsenceObject()
{
return absenceDao.getObject();
}
public Credit getCreditObject()
{
return creditDao.getObject();
}
public Employee getEmployeeObject()
{
return employeeDao.getObject();
}
}
EmployeeServiceTest
@RunWith(MockitoJUnitRunner.class)
public class EmployeeServiceTest
{
@Mock
private GenericDao<Absence> absenceDao;
@Mock
private GenericDao<Credit> creditDao;
@Mock
private GenericDao<Employee> employeeDao;
@InjectMocks
private EmployeeService employeeService;
@Test
public void testGetObject()
{
Mockito.when(absenceDao.getObject()).thenReturn(new Absence());
Mockito.when(creditDao.getObject()).thenReturn(new Credit());
Mockito.when(employeeDao.getObject()).thenReturn(new Employee());
Assert.assertNotNull(employeeService.getEmployeeObject());
Mockito.verify(absenceDao, Mockito.never()).getObject();
Mockito.verify(creditDao, Mockito.never()).getObject();
Mockito.verify(employeeDao, Mockito.times(1)).getObject();
}
}
我希望这有帮助.布拉沃我也学会了回答这个问题.