Имеет ли GroovyMock нестатического метода c указанное поведение? - PullRequest
0 голосов
/ 21 января 2020

Я поместил это в свой тест Спока:

GroovyMock( File, global: true)
File.createNewFile() >> null

... который, как я понимаю, является неортодоксальным / глупым / любопытным: createNewFile - это не статичный c метод.

Используемый код выглядит следующим образом:

if( indexInfoFile.createNewFile() ) {

... из моих экспериментов выясняется, что подобная насмешка createNewFile всегда возвращает false, даже если вы пытаетесь вставить блок в макет :

GroovyMock( File, global: true)
File.createNewFile() >> {
    log.info( 'Hello mum!')
}

... сообщение журнала не распечатывается, но createNewFile снова возвращает false.

Это на самом деле то, что я хотел (т.е. издеваться над возвращением false от createNewFile).

Является ли это преднамеренным, задокументированным поведением?

PS Предостережение: из моего опыта / экспериментов сегодня нет никаких сомнений в том, что этот фиктивный метод заменяет все вхождения вызова этого метода, на любом File экземпляре. Тем не менее, он также имеет некоторые тревожные побочные эффекты: например, каталог, который я создал в своем блоке given до того, как найдены строки 2 GroovyMock, NOT будет существовать впоследствии, все еще в given блок, когда я пошел

myDirPath.toFile().exists()

... Я предполагаю, что это потому, что toFile включает вызов createNewFile ...

1 Ответ

2 голосов
/ 22 января 2020

Поскольку задокументировано , Groovy mocks имеют только дополнительные "маги c" только при использовании с Groovy классами, но я предполагаю, что вы пытаетесь смоделировать java.io.File, что является Java класс JRE. Таким образом, макет Groovy будет вести себя как обычный макет Спока. Поэтому я не знаю, почему вы хотите использовать макет Groovy в первую очередь - возможно, потому, что вы хотите использовать функцию global: true, чтобы избежать рефакторинга для тестирования в вашем классе приложения.

Поскольку вы не показываете нам MCVE - пользователь с репутацией 6,5 тыс. Должен знать лучше - у меня нет возможности узнать, может ли indexInfoFile быть введен в тестируемый класс или метод или это зависимость, созданная внутри метода. В последнем случае вам нужно провести рефакторинг, это так просто. Зависимости должны быть инъекционными, точка.

Что касается ваших фрагментов кода, в них есть несколько ошибок:

  • Метод File.createNewFile() возвращает boolean, поэтому он не имеет смысл заглушить его для возврата null.
  • При создании макета все методы автоматически возвращают false, null или 0, в зависимости от их типа возврата. Поэтому нет необходимости вначале ставить в тупик результат для createNewFile(), если вы хотите, чтобы он возвращал false, потому что он уже делает. был метод c. Это не имеет никакого смысла. Пожалуйста, сначала изучите синтаксис Спока.

Теперь, предположим, что ваш тестируемый класс выглядит следующим образом (уже подготовлен или подвергнут рефакторингу для внедрения зависимости через аргумент метода, аргумент конструктора или сеттер) ...

package de.scrum_master.stackoverflow.q59842227;

import java.io.File;
import java.io.IOException;
import java.util.Random;

public class FileCreator {
  private static final Random RANDOM = new Random();

  public boolean createIndexInfoFile(File indexInfoFile) throws IOException {
    if (indexInfoFile.createNewFile()) {
      System.out.println("File \"" + indexInfoFile + "\" created");
      return true;
    }
    System.out.println("File \"" + indexInfoFile + "\" NOT created");
    return false;
  }

  public static void main(String[] args) throws IOException {
    new FileCreator().createIndexInfoFile(
      new File("_abc_" + RANDOM.nextInt(10000) + ".txt")
    );
  }
}

... тогда вы можете проверить это так:

package de.scrum_master.stackoverflow.q59842227

import spock.lang.Specification

class FileCreatorTest extends Specification {
  def "index info file created"() {
    given:
    File file = Mock() {
      createNewFile() >> true
    }

    expect:
    new FileCreator().createIndexInfoFile(file)
  }

  def "no index info file created"() {
    given:
    File file = Mock()

    expect:
    !new FileCreator().createIndexInfoFile(file)
  }
}

Видите? Нет необходимости в глобальных или Groovy mocks, нормальные mock'ы подойдут просто отлично. Но вам нужно сделать свой код тестируемым, а не использовать причудливые трюки.

...