2013-05-26 3 views
3

У меня есть проект с CDI, и я хотел бы создать модульный тест с помощью mocks. Чтобы управлять макетами, я хотел бы использовать EasyMock и работать с CDI, я нахожу проект cdi-unit, который кажется простым в использовании.единичный тест с CDI-модулем и EasyMock

У меня проблема, связанная с 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-классе в КДИ единицу по @AdditionalClasses):

@Produces 
@ApplicationScoped 
public IStockDao getStockDao() { 
    return EasyMock.createMock(IStockDao.class); 
} 

Когда я запускаю мое модульное тестирование, макет хорошо в тестовом модуле, но я получаю эту ошибку:

java.lang.IllegalArgumentException: Not a mock: org.jboss.weld.proxies.IStockDao$-1971870620$Proxy$_$$_WeldClientProxy

Это один приходит, потому что CDI не дает экземпляр EasyMock IStockDao, но прокси-серверы tance и EasyMock не принимают это в этих методах (например, метод сброса).

Так я заменяю @ApplicationScoped в MockFactory по @Dependent, не проксифицированный экземпляра, но у меня есть новая проблема:

Это аннотация дать новый экземпляр издеваться в каждой точке впрыска, так что я могу использовать его, потому что У меня есть макет в модульном тесте для издевательства метода, вызванного в тестируемом классе. И этот пример макета должен быть таким же в тестируемом классе (это не относится к @Dependent).

Как я могу получить один и тот же экземпляр в модульном тесте и тестированном классе?

Спасибо.

+0

Почему бы вам просто не создать свой макет в тесте и создать объект для тестирования с помощью 'new ResultYearMServiceImpl (StockDao)'? Это и есть цель инъекции зависимостей: возможность вручную вводить макетные зависимости в модульных тестах. Вам не нужен CDI для тестирования класса. –

+0

Я не использую CDI для модульного теста, я использую CDI для всего проекта. ResultYearMServiceImpl сам вводит CDI во многих классах при запуске приложения. Поэтому мне нужно сохранить cdi для модульного теста без изменения моего конструктора для потребностей в тестировании единицы измерения. – Kiva

+0

Вы используете инъекцию зависимостей. Поэтому введите свою зависимость. Вы можете использовать конструктор, сеттер или рефлекторные трюки для доступа к введенному полю. Если ваш издевательский фреймворк не поддерживает эти рефлексивные трюки, это не разумный выбор для использования полевой инъекции. Mockito поддерживает полевые инъекции, используя аннотации. –

ответ

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

я модульное тестирование перехватчика CDI с EasyMock и был такая же проблема, как вы.

Я хотел бы поделиться обходным способом, который использовал. Он состоит в том, чтобы создавать издевательства в области @Dependent. Таким образом, мы можем преодолеть проблему прокси-сервера 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; 
    } 

} 
+0

Да, я тоже нашел это решение, но думаю, что это очень грязное решение. Здесь у нас только один раз макет для класса, поэтому одна переменная для создания (myMock). Как вы это делаете, когда у вас есть 50/60 для создания в очень большом проекте? Вы создаете 50 переменных? Это решение хорошо подходит для решения проблемы для небольшого проекта, но нет для большого проекта. – Kiva

+0

Я согласен и думаю, что худшая часть - это писать методы продюсера. В больших проектах вам все равно придется писать сотни продюсеров, по одному для каждого макетного типа. Итак, надеюсь, что скоро будет выпущено расширение easymock CDI. Я нашел этот http://junitcdi.sandbox.seasar.org/junitcdi-easymock/index.html, но он не очень обновлен. – marciopd

+0

Я создал новый запрос функции в JIRA EasyMock: https://jira.codehaus.org/browse/EASYMOCK-126. Если вы согласны, пожалуйста, проголосуйте. – marciopd

1

Следующая версия CDI-Unit (2.1.1) добавлена ​​поддержка EasyMock таким же образом, что Mockito в настоящее время поддерживается.

Смежные вопросы