java 如何在Cucumber中示例化泛型列表类型以进行测试

qltillow  于 2023-03-28  发布在  Java
关注(0)|答案(1)|浏览(81)

我想重用一个cucumberAssert来验证某个类型的spring Page是否以任何顺序包含一个数据类型
我的代码:

Scenario: List all brands
    Given I have brands in database
      | id | name                          |
      | 1  | brand name for list           |
      | 2  | second brand for list         |
    When I Set GET Brand Endpoint
    When I Set First Page Params
    When I send a GET HTTP request for a page of type com.kugelbit.mercado.estoque.domain.product.Brand
    Then I receive a valid response code for page 200
    Then I receive a valid response page of type com.kugelbit.mercado.estoque.domain.product.Brand
      | id | name |
      | 1  | brand name for list |
      | 2  | second brand for list |
@When("^I send a GET HTTP request for a page of type ([^\"]*)$")
  public void iSendAGetHTTPRequestForPageOfType(String type) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    Class<?> aClass = Class.forName(type);
    final UriComponentsBuilder[] uriComponentsBuilder = {UriComponentsBuilder.fromUriString(this.apiUrl)};
    if(this.urlSearchParams != null) {
      urlSearchParams.forEach((key, value) -> {
        uriComponentsBuilder[0] = uriComponentsBuilder[0].queryParam(key, URLEncoder.encode(value, StandardCharsets.UTF_8));
      });
    }

    CustomPageImpl customPage = new CustomPageImpl(List.of(aClass.newInstance()));

    String uriBuild = uriComponentsBuilder[0].toUriString();
    ResponseEntity<CustomPageImpl<?>> forEntity = (ResponseEntity<CustomPageImpl<?>>) testRestTemplate.exchange(uriBuild, HttpMethod.GET, null, customPage.getClass());
    this.responseEntityPage = forEntity;
  }
@Then("^I receive a valid response page of type ([^\"]*)$")
  public void iReceiveAValidResponsePageOfType(String type, DataTable dataTable) throws ClassNotFoundException {
    Class<?> aClass = Class.forName(type);
    List<?> expected = dataTable.asList(aClass);
    Object[] body = responseEntityPage.getBody().getContent().toArray();
    assertThat(body).containsExactlyInAnyOrderElementsOf(expected);
  }

Assert失败,出现以下情况:
步骤失败java.lang.AssertionError:预期实际值:[{“id”=1,“name”=“列表的品牌名称”},{“id”=2,“name”=“列表的第二品牌”}]以任何顺序精确地包含:[Brand(id=1,name=列表的品牌名称),Brand(id=2,name=列表的第二个品牌)]未找到元素:[品牌(id=1,name=列表的品牌名称),品牌(id=2,name=列表的第二个品牌)]和不需要的元素:[{“id”=1,“name”=“列表的品牌名称”},{“id”=2,“name”=“列表的第二品牌”}]
这意味着期望的是一个Brand类型的列表,这是正确的,我确实有一个DataTable转换。实际的主体具有相同的属性,但类型为Object的列表
我想了两个可能的解决方案:
1.找到一种方法使请求传递正确的Page泛型类型
1.查找另一个Assert,该Assert比较数组中对象的内容,而忽略类型。
注:我的CustomPageImpl来自这个答案:https://stackoverflow.com/a/54423639
下面是一个使用junit测试的项目,它模拟了REST模板通用页面中的Assert问题:https://github.com/giovannicandido/spring-test-generic-resttemplate-question

7lrncoxx

7lrncoxx1#

一种可能性是使用工厂构建ParameterizedTypeReference,这样它就是泛型的:

public class ParameterizedTypeReferenceFactory {

  private static Map<Class<?>, ParameterizedTypeReference<? extends CustomPageImpl<? extends Object>>> parameterizedTypes = Map.of(
    Brand.class,
    new ParameterizedTypeReference<CustomPageImpl<Brand>>() {
    },
    ProductCategory.class,
    new ParameterizedTypeReference<CustomPageImpl<ProductCategory>>() {
    },
    Product.class,
    new ParameterizedTypeReference<CustomPageImpl<Product>>() {
    },
    Market.class,
    new ParameterizedTypeReference<CustomPageImpl<Market>>() {
    },
    MainStock.class,
    new ParameterizedTypeReference<CustomPageImpl<MainStock>>() {
    }
  );

  public static <T> ParameterizedTypeReference<CustomPageImpl<T>> buildCustomPageReference(Class<T> aClass) {
    if (parameterizedTypes.containsKey(aClass)) {
      return (ParameterizedTypeReference<CustomPageImpl<T>>) parameterizedTypes.get(aClass);
    } else {
      throw new IllegalArgumentException(String.format("Cannot find parametrized type for class %s", aClass));
    }
  }
}

并像这样使用它:

ParameterizedTypeReference<? extends CustomPageImpl<?>> typeRef = ParameterizedTypeReferenceFactory.buildCustomPageReference(aClass);
    String uriBuild = uriComponentsBuilder[0].toUriString();
    ResponseEntity<? extends CustomPageImpl<?>> forEntity = testRestTemplate.exchange(uriBuild, HttpMethod.GET, null, typeRef);
    this.responseEntityPage = forEntity;

相关问题