用Java测试时间。更改Spock存根值

时间:2018-12-11 11:39:14

标签: java spring spock java-time

我在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)
        }
    }

}

由于第二个断言,该测试失败。我的存根bean返回了第一次交互声明的值。

  1. 我想了解为什么这种互动方式没有改变。
  2. 我正在寻找有关如何重新设计应用程序的想法。我的目标是

    何时:

    // stub带有某些值的时钟。

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

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

    //执行其他一些逻辑。多次使用时钟。

    然后:

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

2 个答案:

答案 0 :(得分:1)

您误解了Spock。一旦给定的模拟,存根或间谍,您只能声明交互。但是,您可以执行以下操作来声明s tub方法以返回sequence of values

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

package de.scrum_master.stackoverflow

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
  }
}

答案 1 :(得分:0)

我想出了一种解决方案,其中使用了可以计算返回值的功能。

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

,然后在其中替换返回值。

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
    }
}