Scala, Specs2 и общее состояние - PullRequest
2 голосов
/ 21 мая 2019

Я пишу некоторые спецификации2 спецификации; это выглядит так:

class ComponentSpecification extends Specification with Mockito {

  private val dependency = mock[Dependency]
  private val subject = new Component(..)

  "methodOne" should {
    "handle happy path" in {
       val result = subject.methodOne("Param1", 42)
       result must ...
       there was one(dependency).something()
    }

    "deal with border case" in {
       val result = subject.methodOne("", -1)
       result must ...
       there was one(dependency).something()
    }
  }
}

Однако эти тесты не пройдены, поскольку mock[Dependency] является общим.

  • Одним из решений было бы сделать их последовательными и сбрасывать макет перед каждым тестом, но это выглядит странно и, как написано в документе о «Параллельно по умолчанию» :

поощряет написание независимых примеров, когда на результаты данного примера не должны влиять другие

  • Еще бы переместить val к самому тесту. Но хотя я должен быть в состоянии уменьшить дублирование с этим все еще выглядит как странная структура. И похоже, что subject является состоянием, а не должно.

  • Я также могу попытаться использовать менее строгий подход, проверяя с помощью there was atLestOne(dependency).something(), но:

    1. это не подтверждает, что метод был вызван в этом конкретном тестовом примере, и
    2. захват и проверка аргументов болезненны.

Итак, мой вопрос:

Как создать удобочитаемые тесты с подробными проверками на макете.

Большое спасибо.

Ответы [ 2 ]

2 голосов
/ 21 мая 2019

Области применения могут предоставить новое состояние для каждого теста, например,

class ComponentSpecification extends mutable.Specification with Mockito {
  trait FooScope extends Scope {
    val dependency = mock[Dependency]
    val subject = new Component(dependency)
  }

  "methodOne" should {
    "handle happy path" in new FooScope {
      val result = subject.methodOne("Param1", 42)
      there was one(dependency).something()
    }

    "deal with border case" in new FooScope {
      val result = subject.methodOne("", -1)
      there was one(dependency).something()
    }
  }
}

, когда нет необходимости сбрасывать макет перед каждым тестом.

0 голосов
/ 22 мая 2019

Я собирался принять ответ от @Mario Galic. Однако, что касается комментария @Eric (автора Specs2), я закончил с методом, который создает контекст, как и ожидалось, но удаляет дублирование. Используя сопоставление с образцом, я извлекаю интересную часть:

class ComponentSpecification extends mutable.Specification with Mockito {
  def givenOneCallToMethodOneWithDependency(s:String, i:Int):(Result, Dependency) = {
    val dependency = mock[Dependency]
    val subject = new Component(dependency)
    val result = subject.methodOne(s, i)
    (result, dependency)
  }

  "methodOne" should {
    "handle happy path" in new FooScope {
      val (result, dependency) = givenOneCallToMethodOneWithDependency("Param1", 42)
      there was one(dependency).something()
    }

    "deal with border case" in new FooScope {
      val (result, dependency) = givenOneCallToMethodOneWithDependency("", -1)

      there was one(dependency).something()
    }
  }
}
...