thomas77
thomas77

Reputation: 1150

Kotlin shared companion object across junit tests

I have an integration test where I start an embedded MongoDB as a companion object. I want to reuse this piece of code and I am not sure if inheritance is the way to go (if possible).

It is a Spring Boot application:

This is my test:

@RunWith(SpringRunner::class)
@SpringBootTest
class RequestRepositoryTest {

@Autowired lateinit var requestRepository: RequestRepository

  companion object {
    private val starter = MongodStarter.getDefaultInstance()
    private var _mongod: MongodProcess? = null
    private var _mongo: MongoClient? = null

    @BeforeClass
    @JvmStatic fun beforeTest(){
        val port = 27017
        val _mongodExe = starter.prepare(MongodConfigBuilder()
                .version(Version.Main.DEVELOPMENT)
                .net(Net("localhost", port, Network.localhostIsIPv6()))
                .build())
        _mongod = _mongodExe.start()
        _mongo = MongoClient("localhost", port)
    }

    @AfterClass
    @JvmStatic fun afterTest(){
        _mongod?.stop()
    }
  }

  @Test
  fun store() {
    val id = requestRepository.store(Request(requestId = "123"))
    assertNotNull(id)
  }

}

My repository class:

@Repository
class RequestRepository @Autowired constructor(val datastore: Datastore) 
{
  fun store(request : Request) : String = 
  datastore.save(request).id.toString()
}

So my question is which is the 'correct' way to go about this in Kotlin.

Update edit: As an external object the test now looks a lot cleaner and the JUnit external resource is completely reusable across test classes:

Thanks @Lovis

@RunWith(SpringRunner::class)
@SpringBootTest
class RequestRepositoryTest {

  companion object {
      @ClassRule
      @JvmField
      val mongoServer = MongoServer
  }

  @Autowired lateinit var requestRepository: RequestRepository

  @Test
  fun store() {
    val id = requestRepository.store(Request(requestId = "123"))
    assertNotNull( id )
    assertTrue { ObjectId.isValid(id) }
  }

}

Upvotes: 1

Views: 1195

Answers (1)

Lovis
Lovis

Reputation: 10057

You should be able to achieve what you want using jUnit's @ClassRule and ExternalResource. No Kotlin magic needed :-)

Define an object in a separate File:

object MongoServer  : ExternalResource() {
    @Throws(Throwable::class)
    override fun before() {
        // before class
    }

    override fun after() {
       // after class
    }
}

Then use it within each test:

companion object {
    @ClassRule
    @JvmField
    val mongoServer = MongoServer
}

The ClassRule annotation does the trick here, the companion object is necessary to make it static and the @JvmField annotation is necessary to make the field public. Those are restrictions by jUnit's rule system.

Upvotes: 2

Related Questions