知識庫 / Spring RSS 訂閱

使用多種MIME類型測試REST API

REST,Spring,Testing
HongKong
16
04:11 AM · Dec 06 ,2025

1. 概述

本文將重點介紹如何測試具有多種媒體類型/表示形式的 REST 服務。

我們將編寫能夠在多種表示形式之間切換的集成測試,這些表示形式由 API 支持。目標是能夠運行相同的測試,消耗相同的 URI,但請求不同的媒體類型。

2. 目標

任何 REST API 都需要通過一種或多種媒體類型來暴露其資源表示形式。 客户端將通過設置 Accept 標頭來選擇它從服務中請求的表示形式類型。

由於資源可以有多種表示形式,因此服務器必須實現一個負責選擇正確表示形式的機制。 這也稱為內容協商。

因此,如果客户端請求 application/xml,則應收到資源的 XML 表示形式。 如果它請求 application/json,則應收到 JSON。

3. 測試基礎設施

我們將首先定義一個簡單的接口,用於marshaller。這將是主要的抽象,允許測試在不同的Media Type之間切換:

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

然後,我們需要一種方法來根據某種外部配置初始化正確的marshaller。

為此,我們將使用一個 Spring FactoryBean 來初始化marshaller,並使用一個簡單的屬性來確定使用哪個marshaller

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

    @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<IMarshaller> getObjectType() {
        return IMarshaller.class;
    }

    public boolean isSingleton() {
        return true;
    }
}

讓我們來看一下:

  • 首先,Spring 3.1 中引入的 Environment 抽象在這裏被使用——關於此項,請查看有關使用 Properties 與 Spring 的詳細文章
  • 我們從環境中檢索 test.mime 屬性,並使用它來確定要創建的marshaller——這裏使用了 Java 7 的 switch on String 語法
  • 接下來,如果屬性未定義,則默認marshaller將是用於 JSON 支持的 Jackson marshaller
  • 最後——這個 BeanFactory 僅在測試場景中處於活動狀態,因為我們使用了在 Spring 3.1 中引入的 @Profile 支持

這就是全部——該機制能夠根據 test.mime 屬性的值之間切換marshaller。

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支持,marshaller 使用 XStream

public class XStreamMarshaller implements IMarshaller {
    private XStream xstream;

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

    ...

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

請注意,這些marshaller本身並不是 Spring beans。原因在於它們將被 TestMarshallerFactory 通過 bootstrap 注入到 Spring 上下文中,因此無需直接將其聲明為組件。

5. 使用 JSON 和 XML 消費服務

此時,我們應該能夠對部署的服務進行完整的集成測試。 使用marshaller 相當簡單:我們將IMarshaller 注入到測試中:

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

    @Autowired
    private IMarshaller marshaller;

    // tests
    ...

}

Spring 將根據 test.mime 屬性的值確定要注入的精確marshaller。

如果未為該屬性提供值,TestMarshallerFactory 將簡單地回退到默認marshaller——JSONmarshaller。

6. Maven 和 Jenkins

如果 Maven 配置為在已部署的 REST 服務上運行集成測試,則可以使用以下命令執行:

mvn test -Dtest.mime=xml

如果構建使用 Maven 生命週期中的 integration-test 階段:

mvn integration-test -Dtest.mime=xml

為了更詳細地瞭解如何設置 Maven 構建以運行集成測試,請參閲《Maven 集成測試》文章。

使用 Jenkins 時,我們需要配置工作項如下:

This build is parametrized

並且添加了 字符串參數test.mime=xml

一個常見的 Jenkins 配置是讓多個作業運行相同的集成測試,這些測試針對部署的服務 – 一個使用 XML 格式,另一個使用 JSON 格式。

7. 結論

本文介紹瞭如何測試能夠同時支持多種表示形式的 REST API。 大多數 API 都將資源發佈在多種表示形式下,因此測試所有這些表示形式至關重要。 能夠使用相同的測試在所有這些表示形式上運行,這本身就非常酷。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.