Тестирование REST с несколькими типами MIME

Тестирование REST с несколькими типами MIME

1. обзор

В этой статье основное внимание уделяется тестированию службы REST с несколькими типами / представлениями мультимедиа.

Мы напишем интеграционные тесты, способные переключаться между несколькими типами представлений, поддерживаемых API. Цель состоит в том, чтобы иметь возможность выполнять точно такой же тест, используя те же идентификаторы URI службы, просто запрашивая другой тип носителя.

2. цели

Любой API REST должен предоставлять свои Ресурсы в виде представлений, используя один или несколько типов медиа. The client will set the Accept header to choose the type of representation it asks for from the service.с

Поскольку Ресурс может иметь несколько представлений, сервер должен будет реализовать механизм, отвечающий за выбор правильного представления. Это также известно как согласование контента.

Таким образом, если клиент запрашиваетapplication/xml, он должен получить XML-представление ресурса. И если он запрашиваетapplication/json, он должен получить JSON.

3. Инфраструктура тестирования

Начнем с определения простого интерфейса для маршаллера. Это будет основная абстракция, которая позволит тесту переключаться между различными типами медиа:

public interface IMarshaller {
    ...
    String getMime();
}

Затем нам нужен способ инициализации правильного маршаллера на основе некоторой формы внешней конфигурации.

For this, we’ll use a Spring FactoryBean to initialize the marshaller and a simple property to determine which marshaller to use:

@Component
@Profile("test")
public class TestMarshallerFactory implements FactoryBean {

    @Autowired
    private Environment env;

    public IMarshaller getObject() {
        String testMime = env.getProperty("test.mime");
        if (testMime != null) {
            switch (testMime) {
            case "json":
                return new JacksonMarshaller();
            case "xml":
                return new XStreamMarshaller();
            default:
                throw new IllegalStateException();
            }
        }

        return new JacksonMarshaller();
    }

    public Class getObjectType() {
        return IMarshaller.class;
    }

    public boolean isSingleton() {
        return true;
    }
}

Давайте посмотрим на это:

  • во-первых, здесь используется новая абстракцияEnvironment, представленная в Spring 3.1 - для получения дополнительной информации ознакомьтесь сdetailed article on using Properties with Spring

  • мы получаем свойствоtest.mime из среды и используем его, чтобы определить, какой маршаллер создать - здесь работает некоторый синтаксис Java 7switch on String

  • далее маршаллер по умолчанию, если свойство не определено вообще, будет маршаллером Джексона для поддержки JSON.

  • наконец - этотBeanFactory активен только в тестовом сценарии, поскольку мы используем поддержку@Profile, также представленную в Spring 3.1

Вот и все - механизм может переключаться между маршаллерами в зависимости от значения свойстваtest.mime.

4. Маршаллеры JSON и XML

В дальнейшем нам понадобится реальная реализация маршаллера - по одному для каждого поддерживаемого типа носителя.

Для JSON мы будем использоватьJackson в качестве базовой библиотеки:

public class JacksonMarshaller implements IMarshaller {
    private ObjectMapper objectMapper;

    public JacksonMarshaller() {
        super();
        objectMapper = new ObjectMapper();
    }

    ...

    @Override
    public String getMime() {
        return MediaType.APPLICATION_JSON.toString();
    }
}

Для поддержки XML маршаллер используетXStream:

public class XStreamMarshaller implements IMarshaller {
    private XStream xstream;

    public XStreamMarshaller() {
        super();
        xstream = new XStream();
    }

    ...

    public String getMime() {
        return MediaType.APPLICATION_XML.toString();
    }
}

Note that these marshallers are not Spring beans themselves. Причина в том, что они будут загружены в контекст Spring с помощьюTestMarshallerFactory;, поэтому нет необходимости делать их компонентами напрямую.

5. Использование сервиса как с JSON, так и с XML

На этом этапе мы сможем выполнить полное тестирование интеграции с развернутой службой. Использовать маршаллер просто: мы добавим в тестIMarshaller:

@ActiveProfiles({ "test" })
public abstract class SomeRestLiveTest {

    @Autowired
    private IMarshaller marshaller;

    // tests
    ...

}

Spring решит, какой маршаллер будет внедрять, в зависимости от значения свойстваtest.mime.

Если мы не предоставим значение для этого свойства,TestMarshallerFactory просто вернется к маршаллеру по умолчанию - маршаллеру JSON.

6. Мавен и Дженкинс

Если Maven настроен для запуска интеграционных тестов с уже развернутой службой REST, то мы можем запустить его с помощью:

mvn test -Dtest.mime=xml

Или, если это сборка использует фазуintegration-test жизненного цикла Maven:

mvn integration-test -Dtest.mime=xml

Дополнительные сведения о том, как настроить сборку Maven для запуска интеграционных тестов, см. В статьеIntegration Testing with Maven.

С Дженкинсом мы должны настроить работу с:

This build is parametrized

И добавленString parameter:test.mime=xml. **

Обычная конфигурация Jenkins - это задания, выполняющие один и тот же набор интеграционных тестов с развернутой службой - один с XML, а другой с JSON-представлениями.

7. Заключение

В этой статье показано, как протестировать REST API, который работает с несколькими представлениями. Большинство API публикуют свои Ресурсы в нескольких Представлениях, поэтому тестирование всего этого крайне необходимо. Тот факт, что мы можем использовать одни и те же тесты для всех, просто круто.

Полную реализацию этого механизма - с использованием реальных интеграционных тестов и проверкой представлений XML и JSON - можно найти вthe GitHub project.