0

I use this in my MyService.kt.
The useXml is read via application.yml and application-test.yml

@Service
class MyService (
    @Value("\${something.use-xml}")
    var useXml: Boolean = false
) {

  if(useXml) {
    // do this
  } else {
    // do  that 
  }
....
}

this works as expected.

but for the testing I want to use both variation:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class MyFunctionalTest {

    @Value("\${something.use-xml}")
        var useXml: Boolean = false

  //....
@ParameterizedTest
@ValueSource(booleans = [true,false])
fun `do a parameterized test`(useXML : Boolean) {
    useXml = useXML // this is (of course) not setting the variations for `MyService.kt`
    if (useXML) {
      // test this  
    } else {
      // test that
    } 
      
}

I want a possibility where I can set the variable for the application.yml file, so both variations are tested.

Is there any way of doing it?

Joergi
  • 1,527
  • 3
  • 39
  • 82
  • 1
    Using parametrized test for true and false is ... *very* generous/lazy... :) Better would be (as i understand) to do one test (class) with "normal test" profile and another (nested!?) test (class), which also activates "test" profile, but overrides this special property!? -> `@TestPtopertySource` has (one of..second!) highest precedence (s) in [spring boot props](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config)(13.) ..for some reason ;) – xerx593 Oct 31 '22 at 21:49
  • 1
    Simplest (and 3rd highest precedence(12.)): `@SpringBootTest(properties={"foo=bar", "baz=buf",...}) ...@ActiveProfiles(...)` – xerx593 Oct 31 '22 at 21:56
  • also a nice way of doing it... I will have a look! – Joergi Nov 01 '22 at 11:14

1 Answers1

1

Of course, it is possible. You need to inject the service that you are testing and set its useXml value. In your case, it'll look like this:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
internal class MyServiceTest {

    @Autowired
    private lateinit var myService: MyService

    @ParameterizedTest
    @ValueSource(booleans = [true,false])
    fun `do a parameterized test`(useXML : Boolean) {
        myService.useXml = useXML // you have to set the value for the test case

        Assertions.assertEquals(useXML, myService.useXml)
    }
}

However, if I were you and have such a case, I'd go with two totally separate implementations of the same interface, if xml and the other format have something in common. In the end, you will have two classes (you need better naming for that):

  1. MyServiceXml
  2. MyServiceJson

Both this classes will be annotated will @ConditionalOnProperty("\${something.use-xml}") and they will be implementing the same interface.

That will be very easy to test, two different implementations, so two different test classes.

Ice
  • 1,783
  • 4
  • 26
  • 52
  • OMG. how can I have not seen that I'm able to change the value after autowiring it. I have done that 100x before. but I was not aware, that I could control the set value. Thanks a lot – Joergi Nov 01 '22 at 08:09