org.mockito.exceptions.misusing.MissingMethodInvocationException в MOCKITO - PullRequest
4 голосов
/ 31 марта 2020

У меня простой контроллер класса

@RestController
open class MyController() {

@Autowired
lateinit var myInterface: MyInterface

@GetMapping(value = ["/v1/call-Api"], produces = ["application/json"])
fun getData():Response{
   callFx()
   /// Here I have logic
 }

  fun callFx():String{
    return myInterface.getmyStringData()
  }
}

Теперь перейдем к реализации части

MyInterface

@Service
class MyImpl: MyInterface {
  override fun getmyStringData(){
        return "Some string"
    }
}

Обратите внимание, что для MyInterface , у меня есть только один класс реализации.

Теперь перейдем к тестовому примеру класса контроллера

class ControllerTest{

@Autowired
lateinit var myIntF: Myinterface


@Test
fun controllerTest(){         
Mockito.`when`(myIntF.getmyStringData()).thenReturn("Some mock string")
// Some code over here
}

}

После всего этого я продолжаю получать ошибку ниже

  org.mockito.exceptions.misusing.MissingMethodInvocationException: 
  when() requires an argument which has to be 'a method call on a mock'.
  For example:
  when(mock.getArticles()).thenReturn(articles);

  Also, this error might show up because:
  1. you stub either of: final/private/equals()/hashCode() methods.
  Those methods *cannot* be stubbed/verified.
  Mocking methods declared on non-public parent classes is not supported.
  2. inside when() you don't call method on mock but on some other object.

Несмотря на то, что синтаксис кода принадлежит Kotlin, но я упрощаю сценарий для меня. Любой JAVA парень может также помочь мне.

Любая помощь будет очень полезна для меня.

Ответы [ 2 ]

3 голосов
/ 04 апреля 2020

Проблема:

Ниже представлен ваш тестовый класс

class ControllerTest{

@Autowired
lateinit var myIntF: MyInterface


@Test
fun controllerTest(){         
Mockito.`when`(myIntF.getmyStringData()).thenReturn("Some mock string")
// Some code over here
}

Поскольку вы использовали @Autowired, используется реальная реализация, а не фиктивный объект и, следовательно, когда вы делаете Mockito.when(myIntF.getmyStringData()).thenReturn("Some mock string") , вы получаете ошибку when() requires an argument which has to be 'a method call on a mock'. Это связано с тем, что myIntF не является фиктивным объектом.

Решение:

Во-первых, поскольку это тест контроллера, необходимо пометить поле контроллера пометкой @InjectMocks, чтобы ввести в него высмеянный MyInterface объект. Затем вам нужно пометить поле MyInterface с помощью @Mock, что создаст фиктивный объект. Затем вам нужно иметь метод @Before или @BeforeEach с MockitoAnnotations.initMocks(this) для инициализации объектов, аннотированных аннотациями Mockito. Только после этого сработает вызов метода с Mockito.when(mockedObject.methodCall).thenReturn(mockedValue).

class ControllerTest{

@InjectMocks
lateinit var controller: MyController

@Mock
lateinit var myIntF: MyInterface

@BeforeEach
fun init() {
    MockitoAnnotations.initMocks(this)
}


@Test
fun controllerTest(){         
    Mockito.`when`(myIntF.getmyStringData()).thenReturn("Some mock string")
    // Some code over here
    controller.callFx() //this would return "Some mock string"
}
1 голос
/ 04 апреля 2020

Я не знаком с @Autowire, так что это может быть совершенно неверное предположение, но оно также слишком велико для комментария, поэтому здесь все идет.

Исключение в основном объясняет, что объект, который вы ' пытаться издеваться - это не издеваться, и из того, что я вижу, это правда.

Обычно можно сделать что-то вроде:

@Mock
lateinit var myIntF: Myinterface

@Before
fun setUp() {
  MockitoAnnotations.initMocks(this)
}

И теперь издевательство создано, и вы можно настроить его на when, как у вас.

Существуют и другие параметры для инициализации, например, запуск теста с модулем тестирования mockito . Я полагаю, что есть также тестовое правило, и у вас всегда будет mockito- kotlin, что отлично подходит для кода kotlin, и, на мой взгляд, намного проще:

lateinit var myIntF = mock<Myinterface>()

@Test
fun controllerTest(){ 
  myIntF.stub {
   on { getmyStringData() } doReturn "Some mock string"
  }
}

Дело в том, что я думаю, что вы на самом деле не создавали макет, а mockito нуждается в этом, потому что, если я не ошибаюсь, он работает, наследуя от класса, который он насмехается.

Редактировать :

Как указано в комментариях, вы можете протестировать контроллер. Это означает, что вам нужно создать его экземпляр с помощью созданных вами макетов. Один из предложенных способов - использовать @InjectMocks. Что-то вроде:

@InjectMocks
lateinit var controller: MyController

Но, не зная всего тестового кода, трудно сказать, что это именно то, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...