2015-01-22 1 views
1

Я использую Mockito в проекте Java с Spring и Struts, и у меня возникают проблемы с тестирующими действиями.Шпион метод из родительского класса в классе с вложенными mocks с Mockito

Я не использую плагин Struts2 jUnit, чтобы сэкономить время с помощью тестов, используя этот подход: Strut 2.3.1.2 Unit test, how to remove Spring codependency vs NPE with getContext().

Проблема в том, когда в моем действии, когда getText() называется У меня есть исключение NullPointerException.

Я пытаюсь шпионить этот метод, который унаследовал от ActionSupport, но я не нашел способ, потому что действие с аннотацией InjectMocks в тесте.

Вот Simplied пример классов:

Родитель:

public class ActionSupport { 
    public String getText(String aTextName){ 
     return this.getTextProvider().getText(aTextName); 
    } 
} 

Мои действия:

public class MyAction extends ActionSupport { 
    @Autowired private IMyService myService; 

    public String execute(){ 
     getText("SomeText"); 
     myService.something(); 
     return SUCCESS; 
    } 
} 

Тест:

@RunWith(MockitoJUnitRunner.class) 
public class MyClassTest { 
    @Mock private IMyService myService; 
    @InjectMocks private MyAction myAction; 

    @Before 
    public void before() { 
     MockitoAnnotations.initMocks(this); 
    } 

    @Test 
    public void test() { 
     myAction.execute(); 
    } 
} 

Я получаю это исключение :

java.lang.NullPointerException 
    at com.opensymphony.xwork2.util.TextParseUtil.translateVariables(TextParseUtil.java:167) 
    at com.opensymphony.xwork2.util.TextParseUtil.translateVariables(TextParseUtil.java:126) 
    at com.opensymphony.xwork2.util.TextParseUtil.translateVariables(TextParseUtil.java:48) 
    at com.opensymphony.xwork2.util.LocalizedTextUtil.getDefaultMessage(LocalizedTextUtil.java:663) 
    at com.opensymphony.xwork2.util.LocalizedTextUtil.findText(LocalizedTextUtil.java:534) 
    at com.opensymphony.xwork2.util.LocalizedTextUtil.findText(LocalizedTextUtil.java:362) 
    at com.opensymphony.xwork2.TextProviderSupport.getText(TextProviderSupport.java:208) 
    at com.opensymphony.xwork2.TextProviderSupport.getText(TextProviderSupport.java:123) 
    at com.opensymphony.xwork2.ActionSupport.getText(ActionSupport.java:103) 
    at es.MyAction.execute(MyAction.java:148) 

И если я аннотирования MyAction с @Spy поддержания @InjectMocks У меня есть StackOverflowError.

Как я могу шпионить только ActionSupport.getText() и пусть Mockito инъекционные издевается на моем действии?

+1

Я вижу много вопросов, как это при использовании Mock библиотек. Мое общее чувство: если это так больно, чтобы обернуть все такие вещи в штучные объекты, и если ваша система достаточно хорошо разработана, почему бы просто не использовать классы Dummy, реализующие интерфейсы, чтобы избежать такой бессмысленной боли? –

+0

Я не знаю, как это сделать. На самом деле я не знаю, о чем вы действительно говорите :) – Borja

+0

I.e. В идеале ваши модули должны взаимодействовать через интерфейсы, чем конкретные классы реализации; то вы просто напишите фиктивный класс, реализующий ваш интерфейс, и верните ожидаемое значение, которое вы хотите. Таким образом, вы пишете еще один код, но у вас есть идеальный контроль и прозрачность для того, что делают эти фиктивные классы. –

ответ

2

Я бы не использовал @InjectMocks, поскольку он терпит неудачу.

Просто добавьте конструктор к вашему MyAction, все еще используя @Autowired i.e инъекция конструктора. Это также помогает гарантировать требуемые зависимости.

Вам не нужны оба initMocks и MockitoJUnitRunner.

public class MyAction extends ActionSupport { 

    private IMyService myService; 

    @Autowired 
    public MyAction(MyService myService) { 
     this.myService = myService; 
    } 

    public String execute(){ 
     getText("SomeText"); 
     myService.something(); 
     return SUCCESS; 
    } 
} 

@RunWith(MockitoJUnitRunner.class) 
public class MyClassTest { 

    @Mock 
    private IMyService myService; 

    private MyAction myAction; 

    @Before 
    public void setup() { 
     myAction = spy(new MyAction(myService)); 
    } 

    @Test 
    public void test() { 

     assertThat(myAction.execute(), equalTo(Action.SUCCESS)); 

     verify(myAction, times(1)).getText(); 

     verify(myService, times(1)).something(); 
    } 
} 

InjectMocks fails silently

Constructor injection discussion

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