Пересмешивать статические и динамические методы с помощью PowerMock - PullRequest
1 голос
/ 02 февраля 2011

Допустим, у нас есть

public class Foo {
   public static Foo getInstance() {...}

   public Bar bar(Baz baz) {...}
}

Что я хочу сделать, так это смоделировать это в своих модульных тестах.Мне нужно издеваться над статическими и динамическими методами класса Foo.Дразнить getInstance() так же просто, как

import static org.powermock.api.easymock.PowerMock.replace;
import static org.powermock.api.easymock.PowerMock.method;

public class MyTest {

   @Test
   public void myTest() {
      replace(method(Foo.class, "getInstance"))
         .with(method(MyTest.class, "getMockInstance"));
   }

   public static Foo getMockInstance() {
      Foo foo = EasyMock.createMock(Foo.class);
      EasyMock.replay(foo);
      return foo;
   }
}

Вопрос в том, как смоделировать метод bar?

Предыдущий трюк с replace(method(...)).with(method(...)) не работает, так как он не предназначен длядинамические методы.

Попытка смоделировать поверх уже смоделированного класса также не работает:

...
@Test
public void myTest() {
      replace(method(Foo.class, "getInstance"))
         .with(method(MyTest.class, "getMockInstance"));

      Foo foo = Foo.getInstance();  // works well
      Baz baz1 = new Baz();
      Baz baz2 = new Baz();
      EasyMock.expect(foo.bar(baz1)).andReturn(baz2);  // exception thrown
      EasyMock.replay(foo);
}
...

Код выше выдает AssertionError: Unexpected method call bar.

Так как мнесделать оба?Я не хочу помещать насмешку над .bar(...) в getMockInstance, потому что в реальном мире мне нужны некоторые данные, которые недоступны из статического метода getMockInstance.

1 Ответ

3 голосов
/ 02 февраля 2011

Я думаю, что проблема в том, что вы вызываете replay для вашего foo mock дважды, один раз в методе mocked static getMockInstance() и один раз после того, как вы скажете mocked foo ожидать вызова foo.bar(bar1).Попробуйте изменить getMockInstance() на

   public static Foo getMockInstance() {
      Foo foo = EasyMock.createMock(Foo.class);
      return foo;
   }

и затем сказать EasyMock для воспроизведения foo после того, как вы скажете ему ожидать вызова метода bar.Таким образом, MyTest.java будет выглядеть примерно так:

@Test
public void myTest() {
      replace(method(Foo.class, "getInstance"))
         .with(method(MyTest.class, "getMockInstance"));

      Foo foo = Foo.getInstance();  // works well
      Baz baz1 = new Baz();
      Baz baz2 = new Baz();
      EasyMock.expect(foo.bar(baz1)).andReturn(baz2);  // exception thrown
      EasyMock.replay(foo);
}

  public static Foo getMockInstance() {
      Foo foo = EasyMock.createMock(Foo.class);
      return foo;
   }
...