2016-12-05 4 views
1

Мне нужно проверить метод некоторого SLSB, который вызывает другой метод для текущего объекта (используя это ключевое слово), и мне нужно как-то его заглушить.Метод заглушки Mockito, вызванный с помощью этого ключевого слова

Рассмотрим следующий упрощенный код:

@Local 
public interface SomeService{ 
    public int someMethod(); 
    public int anotherMethod(); 
} 

@Stateless() 
public class SomeServiceImpl{ 

    @EJB 
    private SomeDAO sDAO; 

    public SomeServiceImpl(){} 

    public SomeServiceImpl(SomeDAO sDAO){ 
     this.sDAO = sDAO; 
    } 

    @Override 
    public int someMethod(){ 
     int dbValue = sDAO.getSomeDBValue(); // 1st stub required here 
     return dbValue + this.anotherMethod(); // 2nd stub required here 
    } 

    @Override 
    public int anotherMethod(){ 
     return 5; 
    } 
} 

тупиковую метод getSomeDBValue() можно придать издеваться этому классу с @Mock и @InjectMocks аннотации, но я не могу понять, как правильно окурок anotherMethod() , Чтобы его заглушить, мне нужно сделать это на mock-объекте точно, поэтому я попытался передать ссылку на текущий объект в качестве параметра, а в тесте просто пропустить насмешливый объект. Например, если мой метод будет выглядеть следующим образом (без необходимости в методе окурок DAO) ..

@Override 
public int someMethod(SomeServiceImpl sS){ 
    return sS.anotherMethod(); 
} 

Мой тест с созданных вручную издевается будет выглядеть следующим образом:

@Test 
public void someMethodTest() throws Exception { 
    SomeServiceImpl sS = mock(SomeServiceImpl.class); 
    when(sS.someMethod(any(SomeServiceImpl.class))).thenCallRealMethod(); 
    when(sS.anotherMethod()).thenReturn(5); 
    assertEquals(5, sS.someMethod(sS)); 
} 

Метод вызывается на фиктивный объект, ссылка на сам объект передается как параметр, а другой метод - заглушен. Он работал, но это, кажется, очень некрасиво решение и то, что в случае необходимости вводить макет моей DAO с помощью аннотаций, как это:

@RunWith(MockitoJUnitRunner.class) 
public class SomeClassTest{ 

    @Mock 
    SomeDAO sDAO; 

    //@Mock //I can't use those 2 annotations at once 
    @InjectMocks 
    SomeServiceImpl sS; 

    @Test 
    public void someMethodTest() throws Exception { 
     //... 
    } 
} 

Как я понимаю @InjectMocks аннотацию используется для обозначения класса, где глумится аннотированный с @Mock должен быть введен , но для моего уродливого решения мне нужно, чтобы SomeServiceImpl тоже издевался.

Является ли мое решение даже близким к правильному? Как я предполагаю, чтобы заглушить anotherMethod(), чтобы правильно проверить someMethod()? Это хорошая идея, чтобы передать насмешливый экземпляр класса, какой метод я тестирую в аргументе метода? Если да, то как я должен заниматься созданием mocks с аннотациями?

+1

используйте обертку 'Mockito.spy' для проверки объекта unter. –

ответ

0

Вы не должны высмеивать один метод во время тестирования другой метод на такой же класс. Теоретически вы можете это сделать (используя, например, Mokito spy ).

В этом смысле вы приближаетесь к этому на неправильном уровне: на самом деле вам не нужно беспокоиться о том, какие другие методы тестируются вашим методом под вашим тестируемым классом. Понимаете, вы хотите, чтобы проверил, что someMethod() выполняет свой контракт. Если для этого требуется звонок anotherMethod() в вашей производственной среде ... насколько ценным является ваш модульный тест, когда он издевается anotherMethod(), то ?!

Другая идея: вы разделяете проблемы и перемещаете часть anotherMethod() в свой класс X. И тогда ваш тестируемый класс может содержать экземпляр X; и тогда этот экземпляр может быть высмеян.