1

I have a class

object Sender {
    private val emailSender: EmailSender = EmailSender()

    fun sendMessage(text: String) {
        val message = Message(text)
        message.createHeader()
        emailSender.send(message)
    }
}

I need to write a test for sendMessage. I use JUnit5 and MockK libraries. How can I mock emailSender? Is it possible?

Violetta
  • 509
  • 4
  • 12
  • 1
    Presumably you'd need to do dependency injection so you can pass in a custom `EmailSender` to the constructor -- and make `sender` a `class`, not an `object`, while you're at it. – Louis Wasserman Sep 06 '22 at 18:44

1 Answers1

2

This is a quite difficult setup since you initialize the emailSender before anything can be mocked, and the emailSender is not accessible from outside.

If you want to keep Sender as an object and emailSender as a private property, it would help to initialize the emailSender not on startup, but lazily on the first call:

object Sender {
    private val emailSender: EmailSender by lazy { EmailSender() }
    ...
}

Then you can use Mockk's mockConstructor to mock the constructor of EmailSender which does also takes effect for the lazily initialized property emailSender:

@Test
fun test() {
    mockkConstructor(EmailSender::class) {
        every { anyConstructed<EmailSender>().send(any()) } just runs

        Sender.sendMessage("x")

        verify { anyConstructed<EmailSender>().send(any()) }
    }
}
Karsten Gabriel
  • 3,115
  • 6
  • 19