«Слишком мало вызовов», но вызывается метод, и все создается с использованием GroovySpy или GroovyMock - PullRequest
0 голосов
/ 18 июня 2019

У меня есть такой класс:

class A(B b, C c, D d, E e) {

   protected void doSth() {
       test();
   }

   protected void test() {
      System.out.println("test");
   }
}

и я пытаюсь проверить, вызван ли метод doSth(), затем также вызывается метод test(). Методы возвращаемого типа void, поэтому я не могу проверить результат этих методов.

Мои тесты выглядят так

    def "test when doSth"() {
        given: 'A class'
        A aClass = GroovySpy(A, constructorArgs: [GroovyMock(B), GroovyMock(C), GroovyMock(D), GroovyMock(E)) as A

        when:
        A.doSth()

        then:
        1 * A.test()
    }

но этот тест не работает. Это дает мне ошибку «слишком мало вызовов» для метода тестирования. Я действительно запутался, потому что точно такой же пример, но без аргументов в конструкторе, работает отлично.

1 Ответ

0 голосов
/ 19 июня 2019

Во-первых, я не знаю, какой синтаксис у вашего Java-класса. Я полагаю, это не Java, а может быть что-то вроде Kotlin? Понятия не имею, я говорю только на Java и Groovy, когда речь идет о языках JVM. Итак, позвольте мне воссоздать ваш тестируемый предмет так:

package de.scrum_master.stackoverflow.q56652868;

public class A {
  private B b;
  private C c;
  private D d;
  private E e;

  public A(B b, C c, D d, E e) {
    this.b = b;
    this.c = c;
    this.d = d;
    this.e = e;
  }

  protected void doSth() {
    test();
  }

  protected void test() {
    System.out.println("test");
  }

  public static class B {}
  public static class C {}
  public static class D {}
  public static class E {}
}

Надеюсь, это нормально.

Что касается вашего теста, я не уверен, действительно ли тестирование этого взаимодействия (метод test(), называемый doSth()) действительно важно для вашего приложения и должно быть проверено в первую очередь. Я думаю, что этот вид тестирования взаимодействия важен для определенных шаблонов проектирования, где вы, например, хотите проверить, например, субъект уведомляет определенных зарегистрированных наблюдателей, когда происходит что-то конкретное. Тестирование внутренней проводки класса, особенно непубличных методов, обычно не приносит особой пользы и может привести к чрезмерным спецификациям и хрупким тестам, которые необходимо часто обновлять, если не публичный API класса, а только изменения внутренней реализации.

Сказав это, теперь позвольте мне в любом случае ответить на ваш вопрос в образовательных целях.


В вашем тесте не все правильно:

  • Синтаксис неверен. Вам не хватает закрывающего ] для списка аргументов конструктора в строке, определяющей вашего шпиона Groovy.
  • Не совсем ошибка, но зачем переопределять тип вашего шпиона? Вместо A aClass = GroovySpy(A, ...) as A вы в 3 раза убедитесь, что это действительно A. Почему не просто A aClass = GroovySpy(...) или, может быть def aClass = GroovySpy(A, ...)? Не нужно также конвертировать A в себя через as A.
  • Не используйте Groovy для шуток и шпионов, подойдут обычные споки и шпионы. Вам не нужны расширенные фиктивные функции Groovy и, более того, для целевых классов, которые сами не реализованы в Groovy, эти функции все равно не будут работать, как описано в руководстве по Spock. Они бы вели себя как обычные издевательства Спока.
  • Последняя, ​​но не менее важная ошибка: вы пишете A.doSth() и A.test(), как если бы вы имели дело со статическими методами. Зачем? Вам нужно написать aClass.doSth() и aClass.test(), тогда ваш тест пройдет:
package de.scrum_master.stackoverflow.q56652868

import de.scrum_master.stackoverflow.q56652868.A.B
import de.scrum_master.stackoverflow.q56652868.A.C
import de.scrum_master.stackoverflow.q56652868.A.D
import de.scrum_master.stackoverflow.q56652868.A.E
import spock.lang.Specification

class ATest extends Specification {
  def "test when doSth"() {
    given: 'A class'
    A aClass = Spy(constructorArgs: [Mock(B), Mock(C), Mock(D), Mock(E)])

    when:
    aClass.doSth()

    then:
    1 * aClass.test()
  }
}
...