Модульный тест Java: замена тестируемого частного метода - PullRequest
3 голосов
/ 07 января 2010

Есть ли способ заменить логику в закрытом методе при запуске теста JUnit?

Немного предыстории: у нас есть несколько частных методов, которые взаимодействуют с пакетами в контейнере OSGi. Это недоступно в модульном тесте, поэтому методы не пройдут.

Мы рассмотрели JMockIt, но функциональность замены метода, кажется, хочет заставить вас заменить все методы в классе, которые вызывают друг друга.

Реализация будет выглядеть примерно так:

public final doSomething() {  
    firstThing();
    secondThing();
}
private firstThing() {  
    // normal code
}
private secondThing() {  
    // code which is unavailable in a unit test
}

И в модульном тесте будет указана новая реализация secondThing ():

// replace secondThing() in impl with this secondThing()

private secondThing() {  
    // dummy code
}

// run tests

Ответы [ 5 ]

6 голосов
/ 08 января 2010

Вы, безусловно, можете решить эту ситуацию с JMockit. Одним из способов будет определение класса «макета», например:

public class MyTest
{
    @Test
    public void testDoSomething()
    {
        new MockUp<ClassWhichDependsOnOtherBundles>()
        {
            @Mock
            void secondThing()
            {
               // do anything here
            }
        };

        new ClassWhichDependsOnOtherBundles().doSomething();
    }
}

Только метод secondThing() в проверяемом классе будет заменен JMockit. Можно также использовать API ожиданий JMockit с частичной имитацией.

3 голосов
/ 07 января 2010

Вы связываете свою реализацию с созданием объекта osgi (делаете это внутри secondThing () или в самом классе). Если вы передали реализацию в свой класс извне, вы можете использовать заглушку / макет при тестировании.

2 голосов
/ 07 января 2010

Я также думаю, что внедрение зависимостей решило бы эту проблему. Если вам не нужен другой фреймворк в вашем проекте, и это единственное место, которое создает проблемы, вы можете определить интерфейс для secondThing и иметь для этого 2 реализации: одну для исходного кода и пустую для unittest.

1 голос
/ 07 января 2010

Мой совет - переделайте свое приложение. Если вы хотите изменить поведение метода private:

  • сделать его protected / public и переопределить его в макетоподобном объекте
  • переместить функциональность из метода в вспомогательный класс, который можно внедрить (через внедрение зависимостей). Затем смоделируйте этого помощника и вставьте макет в тестируемый класс вместо исходного гелопера.

В качестве обходного пути может использоваться метод манипуляции с байт-кодом, но я не рекомендую такого.

0 голосов
/ 08 января 2010

есть хороший шаблон-заглушка

ProductionClass.java:


public class ProductionClass {
  ...
  //default visibility to make it available for stubbing
  void firstThing(){...}

  ...
}

BlaTest.java (тот же пакет, что и у класса производства):


public class BlaTest {

 @Test
 void test_xx(){
   //use stubbed impl
   ProductionClass sut = new ProductionClassStubbed();
   sut.doSomething();
 }
}

class ProductionClassStubbed extends ProductionClass{

 @Override
 void firstThing(){
   //stub out fill in what you want (like dummy behaviour)
 } 
}

Oneдругая вещь.Я видел последний модификатор в вашем примере кода.Остерегайтесь использования модификатора final .Они злые для проверки.Используйте только если действительно необходимо.

...