https://kotlinlang.org logo
#kotest
Title
# kotest
l

Lukasz Kalnik

01/11/2022, 1:10 PM
I have a test class that looks like this:
Copy code
class NetworkEitherCallAdapterTest : StringSpec({

  private lateinit var server: MockWebServer
  private lateinit var service: CallErrorTestClient

  beforeAny {
      server = MockWebServer()
      server.start()
      service = Retrofit.Builder()
      .baseUrl(server.url("/"))
      .addConverterFactory(GsonConverterFactory.create())
      .addCallAdapterFactory(EitherCallAdapterFactory.create())
      .build()
      .create(CallErrorTestClient::class.java)
  }
  afterAny { server.shutdown() }

  "should return ResponseMock for 200 with valid JSON" {
      server.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}"""))
      val body = service.getEither()
      body shouldBe ResponseMock("Arrow rocks").right()
  }

  // More tests...
I want to run the test class 3 times with different
service
instances (which will use different
ConverterFactory
each). What is the most readable way to achieve it? I don't want to parameterize every test, I want to parameterize the whole class and repeat it.
s

sam

01/11/2022, 1:22 PM
You could look at test factories.
l

Lukasz Kalnik

01/11/2022, 1:32 PM
Thank you for the quick an helpful answer! It looks exactly like what I need ❤️
s

sam

01/11/2022, 1:32 PM
cool 🙂
l

Lukasz Kalnik

01/11/2022, 1:45 PM
How can I make sure though that
server
and
service
are regenerated for each test inside the factory using
beforeAny
?
Basically I want to parameterize the test only on the
jsonConverterFactory
(which in my example actually should replace the hardcoded
GsonConverterFactory.create()
call). But then the
server
and
service
need to be recreated for every test inside the factory.
I my original tests they were `lateinit var`s. I guess I just have to make them nullable in the test factory and safe-call them with
?.
everytime.
s

sam

01/11/2022, 1:57 PM
test factories have beforeTest/beforeAny and it only applies to the tests in that factory
so you can instantiate a factory multiple times, passing in whatever parameters you want
yeah if you want to avoid ? or !!, nothing obvious springs to mind
we need a way to inject a fixture into a test case
l

Lukasz Kalnik

01/11/2022, 2:00 PM
Yes, it's actually logical that I have to make these `var`s nullable, as the test factory is a function and not a class, so I cannot really cheat using
lateinit
as before.
s

sam

01/11/2022, 2:00 PM
right
l

Lukasz Kalnik

01/11/2022, 2:00 PM
It works now with
!!
and I don't mind it.
s

sam

01/11/2022, 2:01 PM
you could pull the server out
and just have start / stop inside the before/after
l

Lukasz Kalnik

01/11/2022, 2:01 PM
True, thanks!
👍🏻 1
No 🙂
That's the point
s

sam

01/11/2022, 2:01 PM
ah because you change it
l

Lukasz Kalnik

01/11/2022, 2:02 PM
I want a new instance of the server in every test so that the server configuration doesn't leak between tests
s

sam

01/11/2022, 2:02 PM
I guess the server is immutable so you need the var
l

Lukasz Kalnik

01/11/2022, 2:03 PM
I want a new server in every test
s

sam

01/11/2022, 2:03 PM
yep
l

Lukasz Kalnik

01/11/2022, 2:04 PM
Because e.g. of such tests:
Copy code
"should return IOError when no response" {
    server!!.enqueue(MockResponse().apply { socketPolicy = SocketPolicy.NO_RESPONSE })

    val body = service!!.getEither()

    body.shouldBeInstanceOf<Left<IOError>>()
      .value.cause.shouldBeInstanceOf<SocketTimeoutException>()
  }
Maybe there is a method to reset the server config every time, but it gives me more peace of mind just to have a new server for every test.
s

sam

01/11/2022, 2:05 PM
I guess the alternative would be to have a function that returns a server and call it inside your tests manually.
Copy code
"mytest" {
  withServer { server- -> 
  }
}
then do the setup/teardown yourself and don't use before/any
l

Lukasz Kalnik

01/11/2022, 2:27 PM
Yes, but that's a bit counterproductive. I rather use the provided test setup/teardown facilities than copy-paste it myself. I can live with a bit of ugliness caused by the
!!
operator.
Thank you for all your help, it's amazing how easy it is to do such complex test setup in Kotest.
s

sam

01/11/2022, 2:28 PM
yeah the power of "tests as functions" really
👍 1
5 Views