Как смоделировать метод, который вызывается из другого метода
Сценарий, в котором я нахожусь
public class SecondClass{
SecondClass(FirstClass fc){
...
}
public void foo(String a,String b){
....
}
}
public class FirstClass{
private SecondClass sc;
public void init(){
sc = new SecondClass(this);
}
public void bar(List<Integer> input){
.....
sc.foo(s1,s2);
}
}
Я хочу получить аргументы String a и b, входящие в foo. Тестовый класс выглядит как ниже
@PrepareForTest({ FirstClass.class, SecondClass.class })
public class SampleTest
{
private String[] texts;
@Test
public void testBar() throws Exception
{
texts = new String[2];
final FirstClass fc = mock(FirstClass.class);
final SecondClass sc = spy(new SecondClass(fc));
doAnswer(invocation -> {
texts = (String[]) invocation.getArguments();
return null;
}).when(sc).foo(anyString(), anyString());
final List<Integer> input = new ArrayList<>();
input.add(1);
fc.bar(input);
System.out.println(texts[0]+"<>"+text[1]);
}
}
Sysout в конце печатает ноль<> ноль. Почему массив текстов не обновляется?
2 ответа
Основная проблема заключается в том, что FirstClass
инициализирует свою собственную копию SecondClass
тогда как вы хотите предоставить макет или подобное.
Подход инверсии управления или внедрения зависимости разработан для смягчения таких ситуаций, предоставляя классам компоненты, которые им необходимы для работы. Можете ли вы вместо этого ввести копию SecondClass
в FirstClass
вместо этого (например, через параметр init()
) Таким образом, вы можете предоставить свой макет во время тестового сценария и, следовательно, протестировать вызов метода.
например
FirstClass fc = new FirstClass();
fc.init(myMockedSecondClass);
fc.bar(...);
// now test the invocations on your mock
Замени это...
public void init(){
SecondClass sc = new SecondClass(this);
}
с сеттером для sc
затем поместите макет в ваш тестовый набор, что позволит вам проверить реальный bar
метод FirstClass
,