Для этого вы можете обратиться к Powermock, но это не обязательно «лучший» ответ на такие проблемы.
По сути, тот факт, что вы вызываете new в своем коде, вызывает у вас огорчение — этим вы создали трудно тестируемый код. Вы можете посмотреть эти видео, чтобы понять, о чем я говорю.
Короче говоря: вместо того, чтобы обращаться к большому молотку Powermock, вы могли бы вместо этого переработать свой код; использовать внедрение зависимостей. Таким образом, вместо того, чтобы создавать эти объекты самостоятельно, ваш тестируемый класс может использовать какой-либо фабричный объект для предоставления необходимого ему объекта. И затем вы можете использовать любой «обычный» макетный фреймворк, такой как EasyMock или Mockito, чтобы создать издевательскую версию этой фабрики.
Изменить: я думаю, вы, возможно, слишком усложнили всю проблему. Видите ли, на самом деле не имеет значения, есть ли базовый класс или два дочерних класса. Дело в том, что для каждого из ваших тестовых методов вы должны точно понимать, по какому пути пойдете. Вы либо хочете, чтобы был создан дочерний элемент1, либо дочерний элемент. Таким образом, я создал для вас упрощенное решение:
package ghostcat.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
class Abc {}
abstract class Base {
void callMethod() {
System.out.println("Base::callMethod");
}
}
class ChildClass1 extends Base {
ChildClass1(Abc abc) {}
}
class MyClass {
public Object build() {
System.out.println("build1");
Base cls = new ChildClass1(new Abc());
System.out.println("build2");
cls.callMethod();
System.out.println("build3");
return null;
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(MyClass.class)
public class MockNewTest {
@Test
public void test() throws Exception {
ChildClass1 mock = Mockito.mock(ChildClass1.class);
PowerMockito.whenNew(ChildClass1.class).withArguments(Mockito.any(Abc.class)).thenReturn(mock);
new MyClass().build();
}
}
Отпечатки:
build1
build2
build3
Вот видите - ничего в базе не вызывается; просто потому, что этот дочерний объект "полностью" издевался.
Суть в том, что для вашего тестируемого кода просто требуется один объект определенного типа; и вы заранее знаете, будет ли это ребенок1 или ребенок2. Итак, вы просто создаете макет для этого класса; и используйте PowerMockito, чтобы вернуть тот макет, который вы только что создали.
Для протокола: некоторое время я играл со шпионами; но они не помогают здесь; и они тоже не обязательны!
15.12.2016