java – Mockito – Mock相同类型的通用对象

我试图使用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();
    }
}

我希望这有帮助.布拉沃我也学会了回答这个问题.

上一篇:java – 验证是否从被测试的方法调用了继承的超类方法


下一篇:java – 使用PowerMockito的void方法模拟单例类