Как издеваться над статическими и нестатическими методами в одном классе с помощью powerMock?
У меня есть простой случай, чтобы проиллюстрировать гораздо более сложный (о, Код наследия, люблю ли я тебя, будут ли менестрели петь чудесные песни Во имя Твое).
Изобразите набор классов следующим образом:
- класс полезности:
package org.osef.test;
public final class A {
private static A instance;
public static String status;
private A() {
initPaths();
}
public static A getInstance(){
if(instance==null){
instance = new A();
}
return instance;
}
private void initPaths() {
A.status = "I have been in the method !";
}
public String doStuff() {
return "stuff done ...";
}
}
- класс, вызывающий его
package org.osef.test;
public class B {
public String doBdo() {
A instance = A.getInstance();
return instance.doStuff();
}
}
- класс, тестирующий эту кучу Ш... гм... штронгли сложный кусок "логики".
Организация пакета.осеф.испытание;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ A.class })
public class BTest {
@Before
public void setUp() {
PowerMock.replace(PowerMock.method(A.class, "getInstance")).with(PowerMock.method(BTest.class, "giveOutInstance"));
A a = A.getInstance();
EasyMock.expect(a.doStuff()).andReturn("lol");
EasyMock.replay(a);
}
@Test
public void testDoBdo() {
B b = new B();
assertEquals("lol", b.doBdo());
assertNull(A.status);
}
public static A giveOutInstance(){
return Whitebox.newInstance(A.class);
}
}
- и другой подход уже было идти следующим образом:
package org.osef.test;
//[imports ommited here but are the same that those of the previous example]
@RunWith(PowerMockRunner.class)
@PrepareForTest({ A.class })
public class BTest {
@Before
public void setUp() {
PowerMock.mockStatic(A.class);
A a = Whitebox.newInstance(A.class);
EasyMock.expect(A.getInstance()).andReturn(a);
PowerMock.replay(A.class);
EasyMock.expect(a.doStuff()).andReturn("lol");
EasyMock.replay(a);
}
@Test
public void testDoBdo() {
B b = new B();
assertEquals("lol", b.doBdo());
assertNull(A.status);
}
}
Но во всех случаях я получаю:
Java.яз..IllegalStateException: нет последнего вызова на макет доступен в орг.изюминка.Изюминка.getControlForLastCall (EasyMock.java: 560) в орг.изюминка.Изюминка.ожидайте (EasyMock.java: 538) в орг.осеф.тест.Бест.setUp (BTest.java: 25) ...
- мне просто нужно проверить этот последний класс А.
- мне нужно избегать логики конструктора (чудовищной и неуместно в моем тестировании метода достаффа"). Я должен проверить этот достафф.
1 ответ:
Я думаю, что ваша проблема заключается в том, что вы не воспроизводите классы, вы только воспроизводите макет экземпляра A в каждом тесте.
PowerMock.replayAll()
это твой друг здесь. Это заставит классы, которые вы ожидаете, быть в режиме воспроизведения, тогда ваш макет экземпляра может быть возвращен вызовом статического метода.Вот образец теста, который я произвел для вашего примера:
import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import org.easymock.EasyMock; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.easymock.PowerMock; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(A.class) public class BTest{ @Test public void thatCallingClassMakesExpectedCalls() { final A mockA = PowerMock.createMock(A.class); EasyMock.expect(mockA.doStuff()).andReturn("lol").anyTimes(); PowerMock.mockStatic(A.class); EasyMock.expect(A.getInstance()).andReturn(mockA).anyTimes(); PowerMock.replayAll(mockA); final B callingClass = new B(); final String doBdo = callingClass.doBdo(); assertThat(doBdo, is("lol")); EasyMock.verify(mockA); PowerMock.verifyAll(); } }