Как да проверя броя на извикванията на частни методи в конструктор?

Имам следния клас:

public class LegacyClass()
{
    public LegacyClass(final int aModeOfOperation)
    {
        if (aModeOfOperation == 0)
        {
            addSomeValues();
            addSomeValues();
        }
        else if (aModeOfOperation == 1)
        {
            addSomeValues();
        }
    }

    private void addSomeValues()
    {
    }
}

Искам да напиша единичен тест, който да провери това

  1. извикването LegacyClass(0) кара частния метод addSomeValues да бъде извикан 2 пъти и
  2. извикването LegacyClass(1) кара частния метод addSomeValues да бъде извикан веднъж.

Знам, че е възможно да се използват шпионски обекти в Mockito/PowerMockito за преброяване на броя извиквания на частни методи, но AFAIK тези подходи работят само ако въпросните методи се извикват след конструкцията на тествания клас .

Възможно ли е да се напише модулният тест, описан по-горе, без да се променя конструкторът на LegacyClass?


person Mentiflectax    schedule 27.11.2013    source източник
comment
Ако тествате частни методи, тогава често може да тествате грешното нещо. Можете ли да тествате резултата от това, което се случва, когато addSomeValues() се извика два пъти? Тестване в черна кутия › тестване в бяла кутия, дори на ниво клас.   -  person vikingsteve    schedule 28.11.2013
comment
@vikingsteve Тестването на резултатите е решението, което използвам сега, защото не можах да намеря нищо по-добро.   -  person Mentiflectax    schedule 28.11.2013
comment
Страхотно, мисля, че всъщност сте намерили по-добро решение. Ако някой някога рефакторира LegacyClass, вашите тестове все още трябва да работят зелено!   -  person vikingsteve    schedule 28.11.2013


Отговори (2)


Мисля, че получавате много по-добра стойност от тестването на единици, ако можете да извършите базирано на състояние тестване (http://blog.jayfields.com/2008/02/state-based-testing.html?m=1) относно изискванията/поведението на публични методи, вместо да тествате броя на извикване на частни методи. Това може да е възможно в някои изолационни рамки, но от гледна точка на тестване на единици не виждам голяма стойност.

Помислете за този единичен тест, ще проверите дали е извикан метод или метод е бил извикан x числа, ако пъти. Тези тестове са тестове за проверка и все още са валидни. НО ключовият фактор е, че повечето рамки за фалшиви обекти ви позволяват да правите тези проверки срещу публични методи (поне в .net). Причината е, че частните методи не са наистина важни от гледна точка на тестване на единици, тъй като те са детайли за вътрешна реализация. Опитайте се да избегнете неуспешни тестове за промяна на схемите на кода.

person Spock    schedule 27.11.2013

Не мисля, че е възможно да се използва mockito, тъй като вие декларирате шпионажа по този начин spy(new LegacyClass()), следователно вашият конструктор се извиква, преди обектът да бъде шпиониран. Може би има начин с PoweverMock, но обикновено не препоръчвам използването на PowerMock, защото не се полагат усилия за преработване на кода до правилен дизайн.

Вместо това горещо ви препоръчвам да преработите своя наследен код до нещо по-тестваемо (разработката, управлявана от тестове, е ключова тук).

Ако абсолютно трябва да запазите този наследен код със съвместими промени, но без PowerMock; Вместо това първо бих увеличил нивото на видимост до видим пакет:

private void addSomeValues() { ... }

След това напишете статичен подклас на LegacyClass във вашия тест и заменете метода addSomeValues, който ще увеличи брояча на извикването super.

public class LegacyCodeTest {
  ...

  static class AddSomeValuesCounteringLegacyClass extends LegacyClass {
    public int counter;
    void addSomeValues() { counter = counter + 1; super.addSomeValues(); }
  }
}

След това във вашия тест вие ненаситявате този клас и отстоявате броя на повикванията;

person Brice    schedule 27.11.2013