6

我正在寻找可以重用 Given & Then 进行单元和集成测试的 BDD java 框架。

换句话说 1.给定一些先决条件。2.When - 取决于环境 3.然后验证When的结果

我希望能够通过更改何时,并保持GivenThen不变,更改测试的类型,例如在简单的 REST 服务中:

  1. 单元测试
    • 给定
      • 生成一些 POJO 对象
    • 什么时候
      • Given接收 POJO
      • 用这个 POJO 调用内部服务
      • 从服务接收 POJO 形式的结果
      • 将收到的 POJO 转发到Then
    • 然后
      • 从何时验证 POJO
  2. 整合测试
    • 给定
      • 生成一些 POJO 对象
    • 什么时候
      • Given接收 POJO
      • 以外部服务格式加密 POJO
      • 调用外部服务
      • 从暴露的服务接收外部服务格式的结果
      • 将接收到的结果转换为 POJO
      • 将收到的 POJO 转发到Then
    • 然后
      • 从何时验证 POJO

因此,在示例中,对于集成和单元测试,GivenThen的行为方式相同,只需将测试范围从 UNIT 更改为 INTEGRATION 即可

有人可以指出我正确的方向吗?

我不想重新发明轮子

4

3 回答 3

8

免责声明:我是 JGiven 的作者。

JGiven正好提供了这一点。它是 Java 的 BDD 框架,其中场景由所谓的阶段类构建。对于您的示例,您需要四个阶段类:GivenInput、WhenInternalService、WhenExternalService 和 ThenOutput。然后你可以写两个测试:

内部服务的单元测试:

public class InternalServiceTest extends 
       ScenarioTest<GivenInput, WhenInternalService, ThenOutput> {

    @Test
    public void internal_service_works_as_expected() {
       given().some_input();
       when().the_internal_service_is_called();
       then().the_result_is_correct();
    } 
}

外部服务的集成测试:

public class ExternalServiceTest extends 
       ScenarioTest<GivenInput, WhenExternalService, ThenOutput> {

    @Test
    public void external_service_works_as_expected() {
       given().some_input();
       when().the_external_service_is_called();
       then().the_result_is_correct();
    } 
}

然后舞台类看起来像这样:

public class GivenInput extends Stage<GivenInput> {
    @ProvidedScenarioState
    InputPojo input;

    public GivenInput some_input() {
       input = new InputPojo();
       return self();
    }
}

public class WhenInternalService extends Stage<WhenInternalService> {
    @ExpectedScenarioState
    InputPojo input;

    @ProvidedScenarioState
    OutputPojo output;

    public WhenInternalService the_internal_service_is_called() {
        output = new InternalService().invoke(input);
        return self();
    }
}

public class WhenExternalService extends Stage<WhenExternalService> {
    @ExpectedScenarioState
    InputPojo input;

    @ProvidedScenarioState
    OutputPojo output;

    public WhenExternalService the_external_service_is_called() {
        ExternalInput externalInput = transformToExternal(input);
        ExternalOutput externalOutput = new ExternalService().invoke(external);
        output = transformToInternal(externalOutput);
        return self();
    }
}

public class ThenOutput extends Stage<ThenOutput> {
    @ExpectedScenarioState
    OutputPojo output;

    public ThenOutput the_result_is_correct() {
        assertThat(output).isNotNull();
        return self();
    }
}

请注意,步骤方法以流利的界面样式编写,以便能够链接多个条件(尽管在您的示例中不需要)。

于 2014-04-18T14:30:36.300 回答
1

如果您使用的是 Java 8,那么您应该看看这个github 项目。

使用它,您可以实现您想要的,而无需创建类。这是由于使用了泛型 + Java 8 Lambda。

以下是一些基本的测试样本:

@Test
public void basicFlowTest() {
 given(1)
  .when("multiplying by 2", givenValue -> 2 * givenValue)
  .then("value should be even", whenValue -> whenValue % 2 == 0);
}

public void multiTypeFlowTest() {
 LocalDateTime localDateTime = LocalDateTime.now();
 DayOfWeek expectedDay = localDateTime.getDayOfWeek();

 given(localDateTime)
  .when("retrieving current day", date -> date.getDayOfWeek())
  .then("days should match", day -> expectedDay == day);
}

@Test
public void assertFlowTest() {
 Integer primeNumber = 17;
 given("a prime number", primeNumber)
  .when("finding dividers naively", number -> IntStream.rangeClosed(1, number)
   .boxed().filter(value -> number % value == 0).collect(Collectors.toList()))
  .then(dividers -> {
   assertEquals("should have two dividers", 2, dividers.size());
   assertEquals("first divider should be 1", 1, (int) dividers.get(0));
   assertEquals(String.format("first divider should be %d", primeNumber), primeNumber, dividers.get(1));
  });
}
于 2016-12-30T00:34:39.030 回答
0

JUnit?

很可能有一个带有@Before方法的抽象基类(即“Given”)和一个带有断言的通用方法(即“Then”)。

于 2013-02-12T08:19:28.000 回答