Модульный тест с CDI Unit и EasyMock
У меня есть проект с CDI, и я хотел бы создать модульный тест с макетами. Для управления имитациями я хотел бы использовать EasyMock, а для запуска с CDI я нахожу проект cdi-unit, который кажется простым в использовании.
У меня есть проблема, чтобы получить макет с EasyMock в контексте CDI. Вот мой юнит тест:
@RunWith(CdiRunner.class)
@AdditionalClasses(MockFactory.class)
public class ResultYearMServiceImplTest {
@Inject
private IStockDao stockDao;
@Inject
private ResultYearMServiceImpl resultYearMService;
@Test
public void getResultList() {
EasyMock.reset(stockDao);
EasyMock.expect(stockDao.getListStocks()).andReturn(null).once()
.andReturn(new ArrayList<DtoStock>()).once();
EasyMock.replay(stockDao);
}
}
IStockDao должен быть фиктивным в тесте, поэтому, чтобы получить его, я хотел бы использовать метод @Produces, подобный этому (в классе MockFactory, переданном модулю cdi @AdditionalClasses):
@Produces
@ApplicationScoped
public IStockDao getStockDao() {
return EasyMock.createMock(IStockDao.class);
}
Когда я запускаю мой модульный тест, макет хорош в модульном тесте, но я получаю эту ошибку:
java.lang.IllegalArgumentException: не фиктивно: org.jboss.weld.proxies.IStockDao$-1971870620$Proxy$_$$_WeldClientProxy
Это происходит потому, что CDI не предоставляет экземпляр EasyMock IStockDao, а представляет собой проксированный экземпляр, а EasyMock не принимает это в этих методах (например, метод сброса).
Поэтому я заменил @ApplicationScoped в MockFactory на @Dependent, который не проксировал экземпляр, но у меня возникла новая проблема:
Эта аннотация дает новый экземпляр макета в каждой точке внедрения, поэтому я могу использовать его, потому что у меня есть макет в модульном тесте для моделирования метода, вызываемого в тестируемом классе. И этот экземпляр mock должен быть одинаковым в тестируемом классе (это не относится к @Dependent).
Как получить один и тот же экземпляр в модульном тесте и в тестируемом классе?
Благодарю.
3 ответа
Игла - ваш друг для тестирования CDI.
public class ResultYearMServiceImplTest {
@Rule
public final NeedleRule needle = new NeedleRule();
@Inject
private IStockDao stockDao;
@ObjectUnderTest
private ResultYearMServiceImpl resultYearMService;
@Test
public void getResultList() {
EasyMock.reset(stockDao);
EasyMock.expect(stockDao.getListStocks()).andReturn(null).once()
.andReturn(new ArrayList<DtoStock>()).once();
EasyMock.replay(stockDao);
}
}
Следующая версия CDI-Unit (2.1.1) добавляет поддержку EasyMock так же, как в настоящее время поддерживается Mockito.
Я тестировал CDI-перехватчик с easymock, и у меня была та же проблема, что и у вас.
Я хотел бы поделиться решением, которое я использовал. Он заключается в создании макетов в @Dependent scope. Таким образом, мы можем решить проблему с прокси-сервером CDI с помощью easymock.
import static org.easymock.EasyMock.createStrictControl;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
/**
* Mock producer. Beans are produced in Dependent scope to not be proxied.
*/
@ApplicationScoped
public class CdiMockProducerUnitTests {
/**
* Mock
*/
private final MyMockClass myMock;
/**
* Constructor creating mocks.
*/
public CdiMockProducerTestesUnitarios() {
myMock = createStrictControl().createMock(MyMockClass.class);
}
/**
* Produces mock in dependent scope.
*
* @return mock
*/
@Produces
@Dependent
public MyMockClass produceMock() {
return myMock;
}
}