Заглушение пользовательского метода TagLib в модульном тестировании контроллера

#unit-testing #grails #mocking #taglib #stubbing

#модульное тестирование #grails #издевательство #taglib #заглушение

Вопрос:

У меня есть метод в пользовательском taglib, подобный этому:

 def deleteAction = {attrs ->
    def id = attrs['id']
    def type = attrs['type']
    def clazz = attrs['class']
    def html = new MarkupBuilder(out)
    html.span(class: "${clazz} ui-icon ui-icon-trash {id:'${id}'}")
}
  

У меня есть контроллер, который использует этот метод, и я пытаюсь заглушить его для модульного теста, поэтому у меня есть следующее:

 def mockMyTagLib = mockFor(MyTagLib)
    mockMyTagLib.demand.deleteAction(1) {id, type, clazz ->
    def html = new MarkupBuilder(new StringWriter())
    html.span(class: "${clazz} ui-icon ui-icon-trash {id:'${id}'}")
}

controller.metaClass.mn = mockMyTagLib.createMock()
  

Но я продолжаю получать следующее:

На данный момент больше не ожидается вызовов ‘DeleteAction’. Завершение запросов.

Я делаю что-то не так здесь? Вот его фактическое использование в контроллере:

 "${mn.deleteAction(id: it.id, type: 'bookProduct', 'class': 'del-book-product')}"
  

Ответ №1:

Следующее взято из Справочной документации по тестированию

… Затем вы указываете имя метода, который вы хотите имитировать, с необязательным диапазоном в качестве его аргумента. Этот диапазон определяет, сколько раз вы ожидаете вызова метода, поэтому, если количество вызовов выходит за пределы этого диапазона (либо слишком мало, либо слишком много), то будет выдана ошибка утверждения. Если диапазон не указан, предполагается значение по умолчанию «1..1», т. е. метод должен быть вызван ровно один раз.

Вы указали demand.DeleteAction(1), что означает, что метод должен быть вызван один и только один раз.

Кроме того, если вы хотите, вы всегда можете сделать свой макет свободным, указав его в качестве второго параметра в mockFor (по умолчанию используется значение strict).

 mockFor(class, loose = false)
  

Комментарии:

1. Grails сообщает мне, что он не может найти свойство «loose», когда я определяю mockFor (Class, loose = false). Тем не менее, я изменил свое требование, пока не заставил его работать, используя диапазон 1 .. 3. (зачем это нужно 3 раза, мне все еще нужно выяснить). Итак, я прошел это, но получаю новую ошибку. Я подозреваю, что это не имеет к этому никакого отношения, поэтому я полагаю, что вы решили мою проблему. Я собираюсь заставить его работать на 100%, и если это действительно не связано с проблемой, вы получите вознаграждение, и я отмечу это как ответ.

2. Удачи! Я надеюсь, что вы решите свои новые проблемы. Странно, что у вас не работает loose. Здесь должны быть просто mockFor (MyClass, false) Javadocs: grails.org/doc/latest/api/grails/test/GrailsUnitTestCase.html