Статический PowerMocking не возвращает ожидаемый объект

У меня проблема с насмешкой над Calendar.getInstance(). Как вы сейчас, этот метод возвращает календарь - объект, над которым я издеваюсь.

Прямо сейчас мой код выглядит так:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Calendar.class)
public class SurveillanceDatabaseTest {
    @Test
    public void testFailingDatabase() throws Exception {
        mockStatic(Calendar.class);
        Calendar calendar = new GregorianCalendar();
        calendar.add(Calendar.HOUR, 1);
        when(Calendar.getInstance()).thenReturn(calendar);
        final Surveillance surveillance = new Surveillance();
        surveillance.checkDatabase();
   }
}

Calendar.getInstance() вызывается в surveillance.checkDatabase() несколько раз, и каждый раз это новый объект, а не ожидаемая имитация Calendar.

Может ли кто-нибудь увидеть, что я делаю неправильно?


person homaxto    schedule 22.01.2013    source источник
comment
В аннотации @PrepareForTest вы должны поместить класс, который использует статический издевательский класс, а не класс, который является статическим издевательским. В вашем случае должно быть @PrepareForTest(Surveillance.class) вместо @PrepareForTest(Calendar.class).   -  person Dominik Kunicki    schedule 24.01.2013
comment
@DominikKunicki преобразовать его в ответ, это правильно, только что проверил ...   -  person Betlista    schedule 18.02.2014


Ответы (3)


Кажется, вам нужно добавить целевой тестовый класс в тег PrepareForTest:
@PrepareForTest({ Calendar.class, Surveillance.class })

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Calendar.class, Surveillance.class })
public class SurveillanceDatabaseTest {
    @Test
    public void testFailingDatabase() throws Exception {
        mockStatic(Calendar.class);
        Calendar calendar = new GregorianCalendar();
        calendar.add(Calendar.HOUR, 1);
        when(Calendar.getInstance()).thenReturn(calendar);
        final Surveillance surveillance = new Surveillance();
        surveillance.checkDatabase();
   }
}

Даже в приведенном выше примере Тома Тресански он понадобится, если мы переместим класс Surveillance куда-нибудь за пределы класса MockCalendarTest.

person Jose Tepedino    schedule 13.04.2015

Я не так хорошо знаком с when(object.call()).andReturn(response);, но предполагаю, что он работает так же, как expect.(object.call()).andReturn(response);. Если это так, то похоже, что вам не хватает воспроизведения класса PowerMock.replay(Calendar.class), и вы пытаетесь сделать полный статический макет вместо частичного статического макета. Это должно решить вашу проблему.

@RunWith(PowerMockRunner.class)
@PrepareForTest(Calendar.class)
public class SurveillanceDatabaseTest {
    @Test
    public void testFailingDatabase() throws Exception {

        Calendar calendar = new GregorianCalendar();
        calendar.add(Calendar.HOUR, 1);

        PowerMock.mockStaticPartial(Calendar.class, "getInstance");  //Mock Static Partial
        expect(Calendar.getInstance()).andReturn(calendar);
        PowerMock.replay(Calendar.class);  // note the replay of the Class!

        final Surveillance surveillance = new Surveillance();
        surveillance.checkDatabase();

        //Whatever tests you need to do here
   }
}
person HardcoreBro    schedule 22.04.2013

Вроде все правильно делаешь. Например, этот тест ниже проходит успешно, доказывая, что Calendar, возвращаемый Calendar#getInstance(), на самом деле является тем, который вы установили с помощью статического имитации.

import static org.junit.Assert.*;
import static org.powermock.api.mockito.PowerMockito.*;

import java.util.Calendar;
import java.util.GregorianCalendar;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Calendar.class)
public class MockCalendarTest {
    @Test
    public void testFailingDatabase() {
        mockStatic(Calendar.class);

        final Calendar testCalendar = new GregorianCalendar();
        testCalendar.add(Calendar.HOUR, 1);
        when(Calendar.getInstance()).thenReturn(testCalendar);

        final Surveillance surveillance = new Surveillance();
        final Calendar resultCalendar = surveillance.checkDatabase();

        assertTrue(testCalendar == resultCalendar);
   }

    public static class Surveillance {
      public Calendar checkDatabase() {
        return Calendar.getInstance();
      }
    }
}

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

person Tom Tresansky    schedule 14.02.2013