Micronaut:将带有 @属性 的值列表注入测试 class 无法按预期工作
Micronaut: Injecting a list of values with @Property to a test class does not work as expected
我如何定义一些特定的 属性 来测试它是一个列表而不仅仅是一个字符串?
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 文件。
如果您在测试 class 中注入 items
列表,那么将 @Property
添加到这样的测试方法中是可行的。像这样:(我知道这是 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,它使用注入的项目。这里的问题是,当您将 someClass
对象注入测试 class 时,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"]
}
}
输出:
幸运的是,这个问题有解决方案。您可以使用 @MockBean
来交付 SomeClass
对象的实现。在这种情况下,您可以定义一个需要 @Property(name="items") List<String> items
参数的方法,因此在测试方法上添加 @Property
注释将覆盖传递给使用 @MockBean
:[=25= 注释的方法的值]
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)
}
}
输出:
我在示例中使用了 Java 和 Spock Framework 测试 (Groovy),但您应该能够使用 Kotlin 实现相同的效果。希望对你有帮助。
我想你有两个选择:
使用@Property(name = "items[0]", value = "Item1")
和@Property(name = "items[1]", value = "Item2")
更改测试以实现 TestPropertyProvider
并通过返回的映射提供配置
我如何定义一些特定的 属性 来测试它是一个列表而不仅仅是一个字符串?
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 文件。
如果您在测试 class 中注入 items
列表,那么将 @Property
添加到这样的测试方法中是可行的。像这样:(我知道这是 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,它使用注入的项目。这里的问题是,当您将 someClass
对象注入测试 class 时,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"]
}
}
输出:
幸运的是,这个问题有解决方案。您可以使用 @MockBean
来交付 SomeClass
对象的实现。在这种情况下,您可以定义一个需要 @Property(name="items") List<String> items
参数的方法,因此在测试方法上添加 @Property
注释将覆盖传递给使用 @MockBean
:[=25= 注释的方法的值]
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)
}
}
输出:
我在示例中使用了 Java 和 Spock Framework 测试 (Groovy),但您应该能够使用 Kotlin 实现相同的效果。希望对你有帮助。
我想你有两个选择:
使用
@Property(name = "items[0]", value = "Item1")
和@Property(name = "items[1]", value = "Item2")
更改测试以实现
TestPropertyProvider
并通过返回的映射提供配置