我可以创建一个springbean作为我的cucumber步骤定义的一部分吗?

qqrboqgw  于 2021-07-09  发布在  Java
关注(0)|答案(2)|浏览(347)

对于某些上下文,我的spring引导应用程序调用外部api,使用 LocalDate.now() 检索各种信息。我们使用cucumber进行测试,在编写步骤定义(如

Given external api "/some/endpoint/2021-04-21" returns csv
  | currency |
  | GBP      |

步骤定义测试代码使用wiremock来模拟该调用,但是由于我们使用 LocalDate.now() 在生产代码中,测试将在2021-04-21之外的任何一天失败。
我解决这个问题的方法是为时钟定义两个bean,然后我们可以将它们自动连接到需要它们的服务中并使用它们 LocalDate.now(clock) . “真实”bean的定义如下:

@Configuration
public class ClockConfiguration {
    @Bean
    public Clock clock() {
        return Clock.systemDefaultZone();
    }
}

测试bean是这样的:

@Profile("cucumber")
@TestConfiguration
public class ClockConfiguration {
    @Bean
    public Clock clock() {
        return Clock.fixed(Instant.parse("2021-02-26T10:00:00Z"), ZoneId.systemDefault());
    }
}

这解决了我的问题,并允许我为我的测试设置一个定义的时间,但我的问题是日期/时间是在测试配置中定义的。我想将其定义为步骤定义的一部分。例如

Given now is "2021-02-26T10:00:00Z"

有一个步骤定义

@Given("now is {string})
public void setDateTime(String dateTime) {
    //Create Clock bean here...
}

我有办法做到这一点吗?或者甚至在cucumber步骤中覆盖现有bean?

jdg4fx2g

jdg4fx2g1#

尝试用变量或静态方法替换日期,其响应可以由步骤定义更改。

@Profile("cucumber")
@TestConfiguration
public class ClockConfiguration {
    @Bean
    public Clock clock() {
        return Clock.fixed(Instant.parse(TestScope.getDateValue()), ZoneId.systemDefault());
    }
}
@Given("now is {string})
public void setDateTime(String dateTime) {
    TestScope.setDateValue(dateTime);
}
yebdmbv4

yebdmbv42#

我设法找到了两个解决这个问题的有效办法。第一个有点复杂,但我基本上创建了一个 Package 类 Clock ,所以一个方法的接口 Clock getClock() 然后有两个实现。一个是真正的豆子,它会回来的 Clock.systemDefaultZone() 还有一个测试bean,它有一个私有的时钟成员,getter只返回这个成员,但最重要的是像setter这样的

public void setClock(String dateTime) {
    this.clock = Clock.fixed(Instant.parse(dateTime), ZoneId.systemDefault());
}

然后我将调用这个setter作为step定义方法的一部分,方法是获取bean。

@Given("now is {string})
public void setDateTime(String dateTime) {
    applicationContext.getBean(MyWrapperClock.class).setClock(dateTime);
}

我发现的第二种方法要简单得多,就是简单地模拟测试配置文件中的时钟。

@Bean 
public Clock clock() {
    return Mockito.mock(Clock.class);
}

然后将其自动关联到step definition类,并执行一个普通的mockito when 例如

@Given("now is {string})
public void setDateTime(String dateTime) {
    when(this.clock.instant()).thenReturn(Instant.parse(dateTime));
    when(this.clock.getZone()).thenReturn(ZoneId.systemDefault());
}

相关问题