Testando o REST com vários tipos MIME
1. Visão geral
Este artigo se concentrará em testar um serviço REST com vários tipos de mídia / representações.
Escreveremos testes de integração capazes de alternar entre os vários tipos de representações suportadas pela API. O objetivo é poder executar exatamente o mesmo teste consumindo exatamente os mesmos URIs do serviço, apenas solicitando um tipo de mídia diferente.
2. Metas
Qualquer API REST precisa expor seus Recursos como representações usando um ou mais Tipos de Mídia. The client will set the Accept header to choose the type of representation it asks for from the service.
Como o Recurso pode ter várias representações, o servidor precisará implementar um mecanismo responsável por escolher a representação correta. Isso também é conhecido como negociação de conteúdo.
Portanto, se o cliente solicitarapplication/xml, ele deverá obter uma representação XML do Recurso. E se ele solicitarapplication/json, ele deve obter JSON.
3. Infraestrutura de teste
Começaremos definindo uma interface simples para um marshaller. Essa será a abstração principal que permitirá que o teste alterne entre diferentes tipos de mídia:
public interface IMarshaller {
...
String getMime();
}
Então, precisamos de uma maneira de inicializar o empacotador certo com base em alguma forma de configuração externa.
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;
}
}
Vamos dar uma olhada nisso:
-
primeiro, a nova abstraçãoEnvironment introduzida no Spring 3.1 é usada aqui - para mais informações, verifique odetailed article on using Properties with Spring
-
recuperamos a propriedadetest.mime do ambiente e a usamos para determinar qual marshaller criar - alguma sintaxe Java 7switch on String funcionando aqui
-
em seguida, o marshaller padrão, caso a propriedade não esteja definida, será o marshaller Jackson para suporte JSON
-
finalmente - esteBeanFactory está ativo apenas em um cenário de teste, pois estamos usando o suporte@Profile, também introduzido no Spring 3.1
É isso - o mecanismo é capaz de alternar entre os marshallers com base em qualquer que seja o valor da propriedadetest.mime.
4. Os Marshallers JSON e XML
Continuando, precisaremos da implementação real do marshaller - um para cada tipo de mídia compatível.
Para JSON, usaremosJackson como a biblioteca subjacente:
public class JacksonMarshaller implements IMarshaller {
private ObjectMapper objectMapper;
public JacksonMarshaller() {
super();
objectMapper = new ObjectMapper();
}
...
@Override
public String getMime() {
return MediaType.APPLICATION_JSON.toString();
}
}
Para o suporte XML, o marshaller usaXStream:
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. A razão para isso é que eles serão inicializados no contexto do Spring peloTestMarshallerFactory;, não há necessidade de torná-los componentes diretamente.
5. Consumindo o serviço com JSON e XML
Nesse ponto, devemos poder executar um teste de integração completo no serviço implantado. Usar o marshaller é simples: injetaremos umIMarshaller no teste:
@ActiveProfiles({ "test" })
public abstract class SomeRestLiveTest {
@Autowired
private IMarshaller marshaller;
// tests
...
}
O Spring decidirá o marshaller exato a injetar com base no valor da propriedadetest.mime.
Se não fornecermos um valor para esta propriedade, oTestMarshallerFactory simplesmente voltará para o marshaller padrão - o marshaller JSON.
6. Maven e Jenkins
Se o Maven estiver configurado para executar testes de integração em um Serviço REST já implantado, podemos executá-lo usando:
mvn test -Dtest.mime=xml
Ou, se esta construção usa a faseintegration-test do ciclo de vida do Maven:
mvn integration-test -Dtest.mime=xml
Para obter mais detalhes sobre como configurar a construção Maven para executar testes de integração, consulte o artigoIntegration Testing with Maven.
Com Jenkins, devemos configurar o trabalho com:
This build is parametrized
E oString parameter:test.mime=xml adicionado. **
Uma configuração comum do Jenkins teria que executar tarefas que executam o mesmo conjunto de testes de integração no serviço implementado - um com XML e outro com representações JSON.
7. Conclusão
Este artigo mostrou como testar uma API REST que funciona com várias representações. A maioria das APIs publica seus recursos em várias representações; portanto, testar tudo isso é vital. O fato de podermos usar exatamente os mesmos testes em todos eles é simplesmente legal.
A implementação completa desse mecanismo - usando testes de integração reais e verificando as representações XML e JSON - pode ser encontrada emthe GitHub project.