测试时间在 Java。更改 spock 存根值

Test time in Java. Change spock stub value

我已经在我的 spring 应用程序中定义了 bean。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Clock;

@Configuration
public class ClockConfiguration {

    @Bean
    Clock getSystemDefaultZoneClock() {
        return Clock.systemDefaultZone();
    }
}

然后在我的测试中我想存根这个bean。

import io.github.jhipster.config.JHipsterConstants
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.test.context.ActiveProfiles
import spock.lang.Specification
import spock.mock.DetachedMockFactory

import java.time.Clock
import java.time.Instant
import java.time.LocalDateTime

import static java.time.ZoneId.systemDefault

@ActiveProfiles(profiles = JHipsterConstants.SPRING_PROFILE_TEST)
@EnableConfigurationProperties
@SpringBootTest(classes = [MyApp])
class ClockTest extends Specification {


    @Autowired
    Clock clock

    //2018-04-01 at 10:00am
    private static Instant REFERENCE_DATE_TIME = LocalDateTime.of(2018, 4, 1, 10, 0)
        .atZone(systemDefault())
        .toInstant()

    //2018-04-01 at 10:00am
    private static Instant OTHER_REFERENCE_DATE_TIME = LocalDateTime.of(2018, 4, 2, 10, 0)
        .atZone(systemDefault())
        .toInstant()

    def "should return different date"() {
        when:
        clock.instant() >> REFERENCE_DATE_TIME
        then:
        clock.instant() == REFERENCE_DATE_TIME
        when:
        clock.instant() >> OTHER_REFERENCE_DATE_TIME
        then:
        clock.instant() == OTHER_REFERENCE_DATE_TIME

    }


    @TestConfiguration
    static class Mocks {
        def detachedMockFactory = new DetachedMockFactory()

        @Bean
        Clock clock() {
            return detachedMockFactory.Stub(Clock)
        }
    }

}

由于第二个断言,此测试失败。我的 stubed bean returns 值由第一次交互声明。

  1. 我想明白为什么这个交互没有改变。
  2. 我正在寻找如何重新设计应用程序的想法。我的目标是

    时间:

    //具有某些值的存根时钟。

    //做一些逻辑。多次使用时钟。

    //将时钟更改为另一个实例。

    //做一些其他的逻辑。多次使用时钟。

    然后:

    //做一些断言。 (例如检查时差)

你误会了 Spock。您只能在给定的模拟、存根或间谍中声明一次交互。但是你可以做什么它声明 s tub 方法到 return a sequence of values.

从您的测试中移除 Spring(引导)混乱,仅使用普通的 Spock,它看起来像这样:

package de.scrum_master.Whosebug

import spock.lang.Specification

import java.time.Clock
import java.time.Instant
import java.time.LocalDateTime

import static java.time.ZoneId.systemDefault

class ClockStubTest extends Specification {
  private static Instant REFERENCE_DATE_TIME = LocalDateTime.of(2018, 4, 1, 10, 0)
    .atZone(systemDefault())
    .toInstant()

  private static Instant OTHER_REFERENCE_DATE_TIME = LocalDateTime.of(2018, 4, 2, 10, 0)
    .atZone(systemDefault())
    .toInstant()

  Clock clock = Stub()

  def "should return different date"() {
    given:
    clock.instant() >>> [REFERENCE_DATE_TIME, OTHER_REFERENCE_DATE_TIME]
    expect:
    clock.instant() == REFERENCE_DATE_TIME
    clock.instant() == OTHER_REFERENCE_DATE_TIME
  }
}

或者您也可以直接在创建的存根范围内声明存根方法:

  // (...)

  Clock clock = Stub() {
    instant() >>> [REFERENCE_DATE_TIME, OTHER_REFERENCE_DATE_TIME]
  }

  def "should return different date"() {
    expect:
    clock.instant() == REFERENCE_DATE_TIME
    clock.instant() == OTHER_REFERENCE_DATE_TIME
  }
}

我想出了一个解决方案,我正在使用可以计算 return 值的功能。

http://spockframework.org/spock/docs/1.2/all_in_one.html#_computing_return_values

并在其中替换 returned 值。

import spock.lang.Specification

import java.time.Clock
import java.time.Instant
import java.time.LocalDateTime

import static java.time.ZoneId.systemDefault

class ClockStubTest extends Specification {
    private static Instant REFERENCE_DATE_TIME = LocalDateTime.of(2018, 4, 1, 10, 0)
        .atZone(systemDefault())
        .toInstant()

    private static Instant OTHER_REFERENCE_DATE_TIME = LocalDateTime.of(2018, 4, 2, 10, 0)
        .atZone(systemDefault())
        .toInstant()

    Clock clock = Stub()

    def "should return different date"() {
        given:
        def now
        clock.instant() >> { now }
        when:
        now = REFERENCE_DATE_TIME
        then:
        clock.instant() == REFERENCE_DATE_TIME
        clock.instant() == REFERENCE_DATE_TIME

        when:
        now = OTHER_REFERENCE_DATE_TIME
        then:
        clock.instant() == OTHER_REFERENCE_DATE_TIME
        clock.instant() == OTHER_REFERENCE_DATE_TIME
        clock.instant() == OTHER_REFERENCE_DATE_TIME
    }
}