Я пишу тестовые примеры JUnit для своих классов обслуживания. Я создал фиктивные данные, чтобы понять свой сценарий.
@Service
MainClass {
@Autowired
C c;
public void someServiceMethod(){
ResultClass someResult = c.getResult(string,string, int, int, List<String>,boolean);
}
}
@Service
public class C {
@Autowired
SomeRepository someRepository;
public ResultClass getResult(string,string, int, int, List<String>,boolean){
ABC returnSomeClassObject = someRepository.getSomeData(String,int,int);
}
}
@Test
MainClassTest {
@MockBean
SomeRepository someRepository;
when(someRepository.getSomeData(anyString(),anyInt(),anyInt())).thenReturn(SomeRepository);
//calling MainClass method
MainClass.someServiceMethod();
}
Метод getSomeData () класса C возвращает объект класса ABC, который имеет значение NULL, а затем устанавливается в другой объект того же типа. После установки значения я получаю NULLPointerException, поскольку ABC равно NULL. Кто-нибудь знает, где я ошибаюсь?
Каковы ваши намерения? Вы хотите только имитировать результат getSomeData () someRepository и протестировать someServiceMethod () MainClass?
@KenChan О да, это хороший аргумент. Если OP намеревался протестировать someServiceMethod, тогда OP должен заглушать getResult, а не getSomeData. Думаю, нужна дополнительная информация.




Вы не возвращаете ожидаемый объект при написании фиктивного оператора
@Service
public class C {
@Autowired
SomeRepository someRepository;
public ResultClass getResult(string,string, int, int, List<String>,boolean){
ABC returnSomeClassObject = someRepository.getSomeData(String,int,int);
//Your return type should be ResultClass
// Where your return statement
// What is ABC?
}
}
@Test
MainClassTest {
@MockBean
SomeRepository someRepository;
when(someRepository.getSomeData(anyString(),anyInt(),anyInt())).thenReturn(SomeRepository);
// Why are you returning SomeRepository, This Should return object of ABC
@MockBean
ABC mockResultClass
when(someRepository.getSomeData(anyString(),anyInt(),anyInt())).thenReturn(mockResultClass);
//calling MainClass method
MainClass.someServiceMethod();
}
Вы вызываете MainClass.someServiceMethod(), который, в свою очередь, вызывает getResult класса C. Вы должны издеваться над классом C и использовать when-thenReturn для getResult() класса C, если вы намерены протестировать someServiceMethod() класса Main. Autowired здесь не будет работать, поскольку это модульный тест, и, следовательно, экземпляр C c в классе Main будет нулевым.
Что-то вроде ниже:
@MockBean
C c;
when(c.getResult(anyString(), anyString(),anyInt(),anyInt(), any(List.class), anyBoolean()).thenReturn(someResult);
c.getResult(string,string, int, int, List<String>,boolean);
Итак, прежде всего, нам нужно четко понимать, что именно вы тестируете. Если вы пытаетесь выполнить модульное тестирование someServiceMethod внутри MainClass, это означает, что вам НЕ следует также тестировать функциональность someRepository. Идея состоит в том, что каждый модульный тест должен тестировать только эту единицу кода. Итак, для этого нам нужно использовать заглушки в качестве замены для того, что на самом деле произойдет, когда вы вызовете методы, принадлежащие другим классам. Затем мы бы написали другой модульный тест только для someRepository.getSomeData(), чтобы убедиться, что он также работает должным образом. Таким образом, когда позже мы получим ошибку, мы будем точно знать, где мы столкнулись с проблемой.
Другая проблема, которую я вижу, заключается в очевидном несоответствии типов возвращаемых значений для getResult() в C. Метод говорит, что возвращает ResultClass, но когда вы вызываете getSomeData, вы ожидаете объект ABC. Либо вы упустили детали, в которых преобразовываете объект обратно в ResultClass, либо это ошибка. Я собираюсь предположить первое, если вы не скажете иначе.
Имея это в виду, давайте напишем наш тест. Вот как бы я написал тест:
@RunWith(SpringRunner.class)
public class MainClassTest {
@Mock
C c;
@InjectMocks
MainClass mainClass;
@Test
public void testSomeServiceMethod {
ResultClass resultClass = new ResultClass(); //relevant constructor details here, mockbean, etc. you get the idea
//set any desired data for resultClass here
Mockito.when(c.getResult(anyString(), anyString(),
anyInt(), anyInt(), any(List.class), anyBoolean()))
.thenReturn(resultClass);
ResultClass newResult = mainClass.someServiceMethod();
//relevant test assertions here
}
}
Как видите, мы создаем ResultClass в тесте и говорим Mockito вернуть его при вызове getResult вместо того, что вы обычно ожидаете вернуть. Хотя сейчас функциональность может показаться ограниченной, это предпочтительнее, поскольку мы тестируем только MainClass, а не остальные вызовы наших методов.
В дополнение к этому мы можем (и должны) писать тесты для getResult в C и getSomeData в SomeRepository. Я предоставлю вам написать эти тесты.
Обновлено: случайно опубликовал немного раньше, сейчас исправляю.
Признаюсь, я не очень хорошо знаком с этим синтаксисом для использования Mockito, но мне кажется, что ваш метод
getSomeDataвозвращаетResultClass, но когда вы вставляете его в заглушку, вы возвращаете объектSomeRepository. Попробуйте создатьResultClassи вернуть его.