Модульный тест с 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.

http://needle.spree.de/

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;
    }

}
Другие вопросы по тегам