Получите отображение с несколькими параметрами как один раз - PullRequest
0 голосов
/ 27 сентября 2018

У меня есть такое отображение:

@GetMapping(value = "/topics", params = "dateRange")
public Set<Integer> getTopicsInRange(@RequestParam DateRange dateRange) {
    return topicService.getTopicsInRange(dateRange);
}

А теперь я бы хотел проверить это как:

private final static DateRange VALID_DATE_RANGE = new DateRange(LocalDate.of(2018, 1, 1), LocalDate.of(2018, 2, 2));

@Test
public void gettingTopicsInRangeShouldReturn200(){
    given().
    .when()
    .get(String.format("/topics?dateRange=%s", VALID_DATE_RANGE)
    .then()
    .statusCode(200);
}

Expected status code <200> doesn't match actual status code <400>.

Iзнаю, что мое решение сработало бы, если бы я изменил свой параметр DateRange на 2 отдельных параметра как:

@GetMapping(value = "/topics", params = {"begin", "end"})
public Set<Integer> getTopicsInRange(@RequestParam Date begin, @RequestParam Date end) {
    return topicService.getTopicsInRange(begin, end);
}

, а затем протестировал бы его как /topics?begin=value&end=value2, но это не то, что я ищу (я думаю, что в случае DateRange было бы 10 полей, в которых 10 параметров были бы слишком излишними) Любые идеи, как мне решить мою проблему?

EDIT Это мой класс DateRange:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class DateRange {
    LocalDate begin;
    LocalDate end;
}

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

Вам нужен способ конвертировать ваш класс DateRange в String и наоборот.Поскольку вы используете Spring, это можно сделать следующим образом:

1) Добавить логику преобразования

@Data
@AllArgsConstructor
@NoArgsConstructor
public class DateRange {

    LocalDate begin;
    LocalDate end;

    private static final String DELIMITER = "_";

    public static DateRange fromFormattedString(String source) {
        if (source != null) {
            String[] tokens = source.split(DELIMITER);
            if (tokens.length == 2) {
                return new DateRange(
                        LocalDate.parse(tokens[0]), // begin
                        LocalDate.parse(tokens[1])  // end
                );
            }
        }
        return null;
    }

    public String toFormattedString() {
        return begin + DELIMITER + end;
    }
}

2) Создать конвертер Spring

import org.springframework.core.convert.converter.Converter;

public class DateRangeConverter implements Converter<String, DateRange> {

    @Override
    public DateRange convert(String source) {
        return DateRange.fromFormattedString(source);
    }
}

3) Зарегистрировать этот конвертер

Это позволит Spring обрабатывать объекты DateRange, переданные как @RequestParam -s

@Configuration
public class WebApiConfiguration extends WebMvcConfigurationSupport {
    ...
    @Override
    public FormattingConversionService mvcConversionService() {
        FormattingConversionService f = super.mvcConversionService();
        f.addConverter(new DateRangeConverter());
        return f;
    }
    ...
}

И, наконец, используйте как:

.get(String.format("/topics?dateRange=%s", VALID_DATE_RANGE.toFormattedString())

или (с необработанной строкой):

.get(String.format("/topics?dateRange=%s", "2018-1-1_2018-2-2")

НО:

Тем не менее, я бы порекомендовалвам нужно использовать отдельные параметры запроса (начало, конец и т. д.), даже если их 10, потому что это:

1) RESTful-способ

2) защищен от ошибок, поскольку параметры запроса заказапереданы, не строго.С другой стороны, упаковка параметров в один объект заставит вас следить за порядком параметров.Более того, вы должны упаковать все параметры в строку, поэтому дополнительные параметры не допускаются, в противном случае логика распаковки может быть нарушена

0 голосов
/ 27 сентября 2018

Добавить DateTimeFormat аннотация:

public class DateRange {

    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate begin;

    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate end;

    // getter and setters
}

Получить объект в контроллере:

@GetMapping(value = "/topics")
public Set<Integer> getTopicsInRange(DateRange dateRange) {
    return topicService.getTopicsInRange(dateRange);
}

И отправить параметры отдельно:

@Test
public void gettingTopicsInRangeShouldReturn200() {
    given()
    .queryParams("begin", LocalDate.of(2018, 1, 1).format(ISO_DATE),
        "end", LocalDate.of(2018, 2, 2))
    .when()
    .get("/topics")
    .then()
    .statusCode(200);
}
...