Как издеваться над частной переменной dao?

У меня есть вызов dao.create(), который я хочу имитировать при тестировании метода. Но я что-то упускаю, так как все еще получаю NPE. Что здесь не так?

class MyService {
    @Inject
    private Dao dao;

    public void myMethod() {
        //..
        dao.create(object);
        //
    }
}

Как я могу издеваться над вызовом dao.create()?

@RunWith(PowerMockRunner.class)
@PrepareForTest(DAO.class)
public void MyServiceTest {

    @Test
    public void testMyMethod() {
        PowerMockito.mock(DAO.class);

        MyService service = new MyService();
        service.myMethod(); //NPE for dao.create()
    }
}

person membersound    schedule 30.11.2012    source источник
comment
Является ли класс ДАО или Дао?   -  person fgb    schedule 30.11.2012
comment
Некоторые хорошие решения зависят от используемой вами инфраструктуры внедрения зависимостей. Пожалуйста, добавьте соответствующий тег (guice, spring, ...)   -  person Andreas Dolk    schedule 30.11.2012


Ответы (5)


Вы не вводите DAO. С mockito вы можете изменить свой тестовый класс, чтобы использовать @InjectMocks и использовать mockito runner.

@RunWith(MockitoJUnitRunner.class)
public void MyServiceTest {
    @Mock
    private Dao dao;
    @InjectMocks
    private MyService myService;
    ...
}

Вы можете узнать больше об InjectMocks в Inject Mocks API.

Более простой способ - изменить вашу инъекцию на инъекцию конструктором. Например, вы можете изменить MyService на

class MyService {
    ...
    private final Dao dao;

    @Inject
    public MyService(Dao dao) {
        this.dao = dao;
    } 
    ...
}

тогда ваш тест вы можете просто пройти издевательский DAO в настройке.

...
@Mock
private Dao dao;

@Before
public void setUp() {
    this.dao = mock(Dao.class);
    this.service = new MyService(dao);
}
...

теперь вы можете использовать verify, чтобы проверить, был ли вызван create, например:

...
   verify(dao).create(argThat(isExpectedObjectBeingCreated(object)));
}

private Matcher<?> isExpectedObjectBeingCreated(Object object) { ... }

Использование инъекции конструктором сделает ваши зависимости более понятными для других разработчиков и поможет при создании тестов :)

person Caesar Ralf    schedule 01.12.2012
comment
Извините за плохой английский :P - person Caesar Ralf; 01.12.2012

Вам все еще нужно установить поле dao с помощью макета. Вы можете использовать отражение для этого.

person dvsander    schedule 30.11.2012

Вам нужно внедрить/установить издевательский объект DAO в свой класс обслуживания.

Если это проект, основанный на весне, вы можете посмотреть @ Spring Junit Testrunner

person cutebug    schedule 30.11.2012

Если вы используете new MyService(), Дао никогда не внедряется. Для внедрения Dao вам необходимо загрузить MyService через ApplicationContext (Spring) или Injector (Guice). Как и в обычном приложении.

person Robe Elckers    schedule 30.11.2012

Как уже говорили другие, вам нужно каким-то образом установить поле dao в вашем классе MyService. Я не уверен, что механизм, позволяющий составному бегуну в вашем тесте использовать как Powermock, так и бегун среды DI (при условии, что Powermock требуется), но до тех пор, пока вы уже используете PowerMock (по причинам, неясным в данном примере) , вы можете воспользоваться Whitebox, чтобы настроить дао вручную.

public void testMyMethod() {
    Dao dao = mock(Dao.class)
    doNothing().when(dao).create(anyObject())); //assuming no return val for dao.create()

    MyService service = new MyService();
    Whitebox.setInternalState(service, "dao", dao);

    service.myMethod(); 
}
person Brian Henry    schedule 01.12.2012