Reputation: 571
How can I define some specific property for testing that is a list and not just a string?
The documentation explains, how to do with string, but I can't set the value
to a list of strings.
application.yml
items:
- "Item 1"
- "Item 2"
Test file:
@MicronautTest(environments = ["test"])
class MyTest {
@Test
@Property(name = "items", value = "Item 1,Item 2") // this does not work
fun justWithOneItem() {
// ...
}
}
On the actual code, this works (as documented here)
Project file:
@Singleton
class SomeClass {
@set:Inject
@setparam:Property(name = "items")
var items: List<String>? = null
// ...
}
I know that I can create an application-test.yml
and do
@MicronautTest(environments = ["test"])
class MyTest {
// ...
}
But I would rather prefer to set it programmatically instead of creating a new env/yaml file.
Upvotes: 4
Views: 9974
Reputation: 12238
I think you have 2 options:
Use @Property(name = "items[0]", value = "Item1")
and @Property(name = "items[1]", value = "Item2")
Change your test to implement TestPropertyProvider
and provide the config via the returned map
Upvotes: 4
Reputation: 42264
Adding @Property
to a test method like that would work if you would inject an items
list in your test class. Something like this: (I know it's Spock test, and not Kotlin, but you should get the point.)
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"]
}
}
However, you are using a bean of SomeClass
that uses injected items. The thing here is that when you inject someClass
object to your test class, the bean is already created and it is immutable. That is why adding @Property
under one of the test methods won't reconstruct the bean object.
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"]
}
}
Luckily, there is a solution to that problem. You can use a @MockBean
to deliver an implementation of SomeClass
object. In this case, you can define a method that expects @Property(name="items") List<String> items
parameter, thus adding a @Property
annotation over a test method will override values passed to the method annotated with @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)
}
}
I have used Java and Spock Framework tests (Groovy) in my examples, but you should be able to achieve the same with Kotlin. I hope it helps.
Upvotes: 3