Scala/Mockito: как смоделировать результат метода, вызываемого внутри другого метода?

Я пытаюсь написать модульный тест Scala с использованием Mockito для метода doSomeBusinessLogic, найденного в следующем классе:

@Service
public class HotelsService {

private final HotelsServiceInt hotelsServiceInt;

public HotelsService(HotelsServiceInt hotelsServiceInt) {
  this.hotelsServiceInt = hotelsServiceInt;
}

public List<String> getHotels(long val1, long val2) {
  return hotelsServiceInt.getHotels(val1, val2)
}

public boolean doSomeBusinessLogic(long val1, long val2) {
  List<String> hotels = getHotels(val1, val2);
  // Do some logic and return true or false
}

А вот интерфейс:

public interface HotelsServiceInt {

@GET("/{val1}/{val2}")
Observable<List<String>> getHotels(
@Path("val1") long val1,                                                                             
@Path("val2") long val2);
}

Вот тест Scala, я написал для него:

import org.mockito._
import org.scalamock.scalatest.MockFactory
import org.scalatest.{BeforeAndAfter, FunSpec}
import org.mockito.Mockito._

 class Spec extends FunSpec with MockFactory with BeforeAndAfter {
   @InjectMocks
   var hotelsServiceInjectedMock: HotelsService = _
   @Mock
   var hotelsService: HotelsService = _

   before{
    hotelsServiceInjectedMock = new HotelsService(hotelsServiceInt)
       MockitoAnnotations.initMocks(this)
   }
   describe("Test") {

   it("Should return false.") {
    val val1 = 1l
    val val2 = 2l
    list = new ArrayList()
    list.add("Hitlon")
    list.add("Sheraton")
    list.add("Rotana")
    doReturn(list).when(hotelsService).getHotels(
                     Matchers.any(), Matchers.any())
    val result = hotelsServiceInjectedMock.doSomeBusinessLogic(val1, val2)
    assert(result == false)
  }}
}

Однако отладка приведенного выше теста показывает, что на самом деле вызывается List<String> hotels = getHotels(val1, val2);.

Есть ли способ выполнить код «doSomeBusinessLogic», но при этом имитировать результат метода «getHotels»?


person Ababneh A    schedule 15.05.2018    source источник
comment
Помогло бы, если бы вы могли включить импорт в свой код, так как несколько фреймворков используют одни и те же имена. В частности, из какой библиотеки MockFactory, это ScalaMock? Похоже, вы смешиваете здесь несколько насмешливых фреймворков.   -  person Alex Savitsky    schedule 15.05.2018
comment
Добавлен импорт в тест   -  person Ababneh A    schedule 15.05.2018
comment
Хорошо, во-первых, вы не включили все импорты (MockitoAnnotations? @InjectMocks? @Mock?). Если вы хотите, чтобы люди помогали вам, не ждите, что они прочитают ваши мысли. Во-вторых, вы, кажется, используете здесь несколько насмешливых фреймворков. Макеты, инициализированные с помощью одного фреймворка, не будут работать при вызове из другого фреймворка.   -  person Alex Savitsky    schedule 15.05.2018


Ответы (1)


Да, это достижимо, потому что у вас есть файл:

private final HotelsServiceInt hotelsServiceInt;

Вы можете имитировать hotelsServiceInt в своем тестовом классе и возвращать свои имитированные результаты. Перед вызовом doSomeBusinessLogic просто верните имитированный список, и все готово. Вам также необходимо изменить типы переменных для @Mock и @InjectMock, как написано ниже:

   @Mock
   var hotelsServiceInitMock: HotelsServiceInt = _
   @InjectMocks
   var hotelsService: HotelsService = _
   //then do this:
   doReturn(list).when(hotelsServiceInitMock).getHotels(
                 Matchers.any(), Matchers.any())

Теперь вы должны быть в состоянии получить требуемый результат.

person Nyle Hassan    schedule 15.05.2018
comment
Не будет работать! hotelsServiceInt.getHotels не существует. Если я это сделаю, компилятор не сможет разрешить ссылку, выдав ошибку. - person Ababneh A; 15.05.2018
comment
Вы делаете отелиServiceInt.getHotels в тестовом классе? - person Nyle Hassan; 15.05.2018
comment
Нет, я этого не делаю. Я просто говорю, что если я это сделаю, это не сработает. - person Ababneh A; 15.05.2018
comment
взгляните на это: stackoverflow.com/questions/41663476/ - person Nyle Hassan; 15.05.2018
comment
Пожалуйста, посмотрите обновленный ответ, я вижу, что вы не издевались над объектом HotelsServiceInt, его нужно издеваться, и @InjectMock затем свяжет этот издевательский объект с тестовым классом. Я надеюсь, что это решает ваш запрос - person Nyle Hassan; 16.05.2018