Micronaut:将@Property的值列表注入测试类无法正常工作

时间:2019-10-29 17:46:05

标签: micronaut

如何定义一些特定的测试属性,该属性是列表而不是字符串?

documentation explains, how to do with string,但我无法将value设置为字符串列表。

application.yml

items:
  - "Item 1"
  - "Item 2"

测试文件:

@MicronautTest(environments = ["test"])
class MyTest {

    @Test
    @Property(name = "items", value = "Item 1,Item 2") // this does not work
    fun justWithOneItem() {
        // ...
    }
}

在实际代码上,这有效(as documented here

项目文件:

@Singleton
class SomeClass {
    @set:Inject
    @setparam:Property(name = "items")
    var items: List<String>? = null

    // ...
}

我知道我可以创建一个application-test.yml并这样做

@MicronautTest(environments = ["test"])
class MyTest {
    // ...
}

但是我宁愿以编程方式设置它,而不是创建一个新的env / yaml文件。

2 个答案:

答案 0 :(得分:1)

如果要在测试类中插入@Property列表,则将items添加到类似的测试方法中将是可行的。像这样:(我知道这是Spock测试,不是Kotlin,但您应该明白这一点。)

package com.github.wololock.micronaut.products

import io.micronaut.context.annotation.Property
import io.micronaut.test.annotation.MicronautTest
import spock.lang.Specification

@MicronautTest(environments = ["test"])
class MyTest extends Specification {

    @Property(name = "items")
    List<String> items

    def "should use default items"() {
        expect:
        items == ["Item 1", "Item 2"]
    }

    @Property(name = "items", value = "Item 3,Item 4,Item 5")
    def "should override default items"() {
        expect:
        items == ["Item 3", "Item 4", "Item 5"]
    }
}

但是,您正在使用SomeClass的bean,该bean使用注入的项。这里的问题是,当您向测试类中注入someClass对象时,该bean已经创建并且是不可变的。这就是为什么在其中一种测试方法下添加@Property不会重建bean对象的原因。

package com.github.wololock.micronaut.products

import io.micronaut.context.annotation.Property
import io.micronaut.test.annotation.MicronautTest
import spock.lang.Specification

import javax.inject.Inject

@MicronautTest(environments = ["test"])
class MyTest extends Specification {

    @Inject
    SomeClass someClass

    def "should use default items"() {
        expect:
        someClass.items == ["Item 1", "Item 2"]
    }

    @Property(name = "items", value = "Item 3,Item 4,Item 5")
    def "should override default items"() {
        expect:
        someClass.items == ["Item 3", "Item 4", "Item 5"]
    }
}

输出:

enter image description here

幸运的是,有一个解决该问题的方法。您可以使用@MockBean来实现SomeClass对象的实现。在这种情况下,您可以定义一个期望使用@Property(name="items") List<String> items参数的方法,因此在测试方法上添加@Property注释将覆盖传递给用@MockBean注释的方法的值:

package com.github.wololock.micronaut.products

import io.micronaut.context.annotation.Property
import io.micronaut.test.annotation.MicronautTest
import io.micronaut.test.annotation.MockBean
import spock.lang.Specification

import javax.inject.Inject

@MicronautTest(environments = ["test"])
class MyTest extends Specification {

    @Inject
    SomeClass someClass

    def "should use default items"() {
        expect:
        someClass.items == ["Item 1", "Item 2"]
    }

    @Property(name = "items", value = "Item 3,Item 4,Item 5")
    def "should override default items"() {
        expect:
        someClass.items == ["Item 3", "Item 4", "Item 5"]
    }

    @MockBean(SomeClass)
    SomeClass someClassMock(@Property(name = "items") List<String> items) {
        return new SomeClass(items)
    }
}

输出:

enter image description here

我在示例中使用了Java和Spock Framework测试(Groovy),但是您应该能够通过Kotlin实现相同的功能。希望对您有所帮助。

答案 1 :(得分:1)

我认为您有2种选择:

  1. 使用@Property(name = "items[0]", value = "Item1")@Property(name = "items[1]", value = "Item2")

  2. 更改测试以实现TestPropertyProvider并通过返回的映射提供配置