【问题标题】:Kotlin MockMvc test fails: "Content type not set"Kotlin MockMvc 测试失败:“未设置内容类型”
【发布时间】:2022-01-08 19:11:57
【问题描述】:

在尝试使用 ResultActionsDsl (content { contentType(MediaType.APPLICATION_JSON) }) 验证内容类型时,我目前收到“未设置内容类型”错误。

我已尝试在 @PostMapping 中指定内容类型,并将 @ResponseBody 添加到函数中:在其他地方已建议的两件事,但不喜欢。

想法?

这里是控制器位:

@RestController
@RequestMapping("/api/retailer")
class RetailerController(val retailerService: RetailerService, val authHelper: AuthHelper) {

    @PostMapping("/distributor/orders",
        produces = [MediaType.APPLICATION_JSON_VALUE])
    @ResponseBody
    suspend fun postDistributorOrder(
        @RequestParam cohort: String,
        @RequestParam sku: Sku,
        @RequestParam quantity: Qty,
        @RequestParam price: Price,
        request: HttpServletRequest
    ): OrderId {
        val retailerId = authHelper.getRetailerId(request)
        return retailerService.postDistributorOrder(cohort = cohort, retailerId = retailerId, sku = sku, quantity = quantity, price = price)
    }

...

}

这里是测试位:


@WebMvcTest(RetailerController::class)
class RetailerControllerTest {

...

    @BeforeEach
    fun setup() {
        mvc = MockMvcBuilders
            .webAppContextSetup(context)
            .apply<DefaultMockMvcBuilder>(springSecurity())
            .build()
    }


    val methodUrl = "${baseUrl}/distributor/orders?cohort=redGroup&sku=111&quantity=100&price=5"

    @Test
    fun `should succeed with TeamBot role`() {
        // given
        val user = user(FastUserDetails(userWithTeamBotRole))

        // when
        val resultDsl = mvc.post(methodUrl) { with(user) }

        // then
        resultDsl.andExpect {
            status { isOk() }
            content { contentType(MediaType.APPLICATION_JSON) } // TODO: Why are we getting "Content type not set"?
        }
    }

...

}

这里是依赖位:


plugins {
    id("org.springframework.boot") version "2.5.4"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
    kotlin("jvm") version "1.5.20"
    kotlin("plugin.spring") version "1.5.20"
    kotlin("plugin.serialization") version "1.5.20"
}

dependencies {

    val kotlinWrappersKotlinVersion = "1.4.32"
    val kotlinWrappersVersion = "pre.153"
    val kotlinxHtmlVersion = "0.7.2"
    val kotlinCssVersion = "1.0.0"

    implementation(platform("io.projectreactor:reactor-bom:2020.0.8"))
    implementation("io.projectreactor:reactor-core")

    implementation(kotlin("reflect"))
    implementation(kotlin("stdlib-jdk8"))

    implementation("org.springframework.boot:spring-boot-starter")
    implementation("org.springframework.boot:spring-boot-starter-security")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.data:spring-data-redis:2.5.0")
    implementation("redis.clients:jedis:3.6.0")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("io.jsonwebtoken:jjwt:0.9.1")
    implementation("org.json:json:20160810")
    implementation("javax.xml.bind:jaxb-api")

    implementation("com.github.doyaaaaaken:kotlin-csv-jvm:0.15.2")

    implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:${kotlinxHtmlVersion}")
    implementation("org.jetbrains:kotlin-css:${kotlinCssVersion}-${kotlinWrappersVersion}-kotlin-${kotlinWrappersKotlinVersion}")
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2")

    implementation("org.springframework.boot:spring-boot-starter-webflux")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:1.5.2")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.5.2")
    implementation("io.springfox:springfox-boot-starter:3.0.0")

    implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.3.1")

    developmentOnly("org.springframework.boot:spring-boot-devtools")

    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.springframework.security:spring-security-test")
    testImplementation("io.projectreactor:reactor-test")
    testImplementation("io.mockk:mockk:1.12.0")
    testImplementation("com.ninja-squad:springmockk:3.0.1")
    testImplementation("io.kotest:kotest-assertions-core:4.6.1")
    testImplementation("org.apache.httpcomponents:httpclient:4.5.13")
    testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.5.1")
    testImplementation("app.cash.turbine:turbine:0.7.0")
    testImplementation(kotlin("test"))

}

tasks.withType<KotlinCompile> {

    sourceCompatibility = "14"
    targetCompatibility = "14"

    kotlinOptions {
        allWarningsAsErrors = false
        suppressWarnings = false
        verbose = false
        freeCompilerArgs = listOf("-Xjsr305=strict", "-Xopt-in=kotlin.time.ExperimentalTime", "-Xopt-in=kotlin.RequiresOptIn")
        jvmTarget = "14"
        languageVersion = "1.5"
        apiVersion = "1.5"
    }
}

【问题讨论】:

    标签: kotlin content-type mockmvc


    【解决方案1】:

    根据this SO answer,您可能需要指定字符编码。 Java版本:

    MvcResult result = mvc.perform(post("/administration")
        .contentType(MediaType.APPLICATION_JSON)
        .content(json)
        .characterEncoding("utf-8"))
        .andExpect(status().isOk())
        .andReturn();
    

    如果您需要 Kotlin DSL 版本,我会编辑这篇文章。

    【讨论】:

    • 在 post 请求中添加 contentType、characterEncoding 和“接受”contentType 仍会导致响应中出现“未设置内容类型”。
    • @MichaelS.Kelly 你试过使用 Postman 吗?这会给你更好的调试能力
    • 我希望测试成为自动化构建管道的一部分。此外,有些 API 是 Server Sent Events,Postman 不支持。
    • 好主意。在测试之外运行它时,我得到了一个内容类型的标题。而且,这正是我所期望的:'application/json'。
    猜你喜欢
    • 2017-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 2014-11-11
    相关资源
    最近更新 更多