Mockito / PowerMock: как сбросить статическую переменную в SUT? - PullRequest
6 голосов
/ 26 апреля 2011

Я ненавижу внедрять юнит-тесты в унаследованную базу кода, но я должен это сделать.
До сих пор я успешно внедрил модульное тестирование в унаследованную базу кода с использованием Mockito и PowerMock.Работал безупречно, пока я не столкнулся с такой ситуацией:

в SUT, есть несколько статических переменных (которые я высмеивал с помощью PowerMock, насмешливых статических методов и конструкторов насмешек).
Теперь в первом тестовом методе все работало нормально, и смоделированная статическая переменная вернула ожидаемое выходное значение.
но в последующих тестовых методах макет статического объекта всегда возвращает значение, которое было установлено в первом тесте, хотя я вызывал reset () для него перед тестами.

// legacy code base:
public class SUT {
  private static Collaborator1 c1 = null;
  private static Collaborator2 c2 = null;

  public SUT(param1) {
    if (c1 == null) {
        c1 = Collaborator1.instance(param1);
        c2 = new Collaborator2(c1);
    } else {
    }
  }
}



// newly introduced unit tests:
@RunWith(PowerMockRunner.class)
@PrepareForTest({
    SUT.class,                  // to mock: new Collaborator2(..), as required by PowerMock when mocking constructors
    Collaborator1.class,        // to mock: Collaborator1.instance(..), as required by PowerMock in mocking static methods
})
public class SUTTest {

  private SUT sut;

  private Collaborator1 c1 = mock(Collaborator1.class);
  private Collaborator2 c2 = mock(Collaborator2.class);

  @Before  
  public void setup() {
    // mock c1:
    PowerMockito.mockStatic(Collaborator1.class);
    when(Collaborator1.instance(param1)).thenReturn(c1);

    // mock c2:
    PowerMockito.whenNew(Collaborator2.class).withArguments(c1).thenReturn(c2);

    reset(c1);
    reset(c2);

    sut = new SUT(param1);
  }

  @Test
  public void test1() {
    when(c2.foo(input1)).thenReturn(out1); 

    // do something
  }

  @Test
  public void test2() {
    when(c2.foo(input2)).thenReturn(out2);    // BANG!!! c2.foo(input2) always return "out1"

    // do something
  }
}



Поскольку конструктор SUT создает экземпляры c1 и c2 только в том случае, если статический c1 равен нулю, они (c1, c2) не восстанавливаются в вызовах подпоследовательности.Что я не понимаю, так это то, почему сброс (c1), сброс (c2) не имеют никакого эффекта в test2?

Есть идеи?

Ответы [ 2 ]

5 голосов
/ 27 апреля 2011

Понял, наконец-то. В принципе, я не могу установить заглушку (переменную статического экземпляра) в двух разных тестовых прогонах. Я должен настроить ожидаемое поведение в первом @Before.
Поэтому вместо использования

  @Before  
  public void setup() {
    ...
  }

  @Test
  public void test1() {
    when(c2.foo(input1)).thenReturn(out1); 
  }

  @Test
  public void test2() {
    when(c2.foo(input2)).thenReturn(out2); 
  }

Я должен использовать эту последовательность:

@Before  
  public void setup() {
    when(c2.foo(input1)).thenReturn(out1); 
    when(c2.foo(input2)).thenReturn(out2);
  }

  @Test
  public void test1() {
    // do something
  }

  @Test
  public void test2() {
    // do something
  }

Какие-то ограничения (ошибка?) В PowerMock / Mockito?

0 голосов
/ 01 апреля 2016

Попробуйте перенести настройку статического макета в метод настройки @BeforeClass, но оставьте свой вызов reset (mocks) в методе test setup (). Вы хотите настроить mockStatic только один раз, но поскольку они статичны, вам нужно будет сбрасывать их при каждом тесте, иначе они будут сбиты с толку последующими тестами.

т.е. попробовать

@BeforeClass  
public void setupClass() {
    // mock c1:
    PowerMockito.mockStatic(Collaborator1.class);
    when(Collaborator1.instance(param1)).thenReturn(c1);

    // mock c2:
    PowerMockito.whenNew(Collaborator2.class).withArguments(c1).thenReturn(c2);
}

@Before  
public void setup() {
  reset(c1);
  reset(c2);

  sut = new SUT(param1);
}

@Test
public void test1() {
  // do something
}

...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...