Solution: Specify expectations

fun Notifier.notifyUser(user: User?) { user ?: return // or // if(user == null) return if(!checkId(user.id)) throw IncorrectId() require(user.name != null) { "Name cannot be null" } require(user.surname != null) { "Surname cannot be null" } check(initialized) { "Notifier is not initialized" } val result = notifyPerson(user.id) assert(result) }

Example solution in playground

import org.junit.Assert.assertThrows import org.junit.Test import java.lang.AssertionError import java.lang.IllegalStateException import kotlin.test.assertEquals fun Notifier.notifyUser(user: User?) { user ?: return // or // if(user == null) return if(!checkId(user.id)) throw IncorrectId() require(user.name != null) { "Name cannot be null" } require(user.surname != null) { "Surname cannot be null" } check(initialized) { "Notifier is not initialized" } val result = notifyPerson(user.id) assert(result) } data class User( val id: Int, val name: String?, var surname: String? ) class IncorrectId : Error() interface Notifier { /** * Indicate instance readiness to notify users */ val initialized: Boolean /** * Notifies person * @param id Is an id of user we want to notify * @return Was the operation successful */ fun notifyPerson(id: Int): Boolean /** * Checks if we can send message to the following id */ fun checkId(id: Int): Boolean } class RequirementsChecks { @Test fun `Function sends message for correct arguments and state`() { val notifier = FakeNotifier(initialized = true) val id = 123 notifier.notifyUser(User(id, "Ben", "Barack")) assertEquals(setOf(id), notifier.usersNotified) } @Test fun `Function does nothing when user is null`() { val notifier = FakeNotifier(initialized = true) notifier.notifyUser(null) assertEquals(setOf(), notifier.usersNotified) } @Test fun `Function throws IllegalArgumentException when name is null`() { val notifier = FakeNotifier(initialized = true) val id = 123 assertThrows(IllegalArgumentException::class.java) { notifier.notifyUser(User(id, null, "Kowalski")) } } @Test fun `Function throws IllegalArgumentException when surname is null`() { val notifier = FakeNotifier(initialized = true) val id = 123 assertThrows(IllegalArgumentException::class.java) { notifier.notifyUser(User(id, "Barack", null)) } } @Test fun `Function throws IllegalStateException when notifier is not initialized`() { val notifier = FakeNotifier(initialized = false) val id = 123 assertThrows(IllegalStateException::class.java) { notifier.notifyUser(User(id, "Mike", "Bull")) } } @Test fun `Function throws IncorrectId when id is incorrect`() { val notifier = FakeNotifier(initialized = true) assertThrows(IncorrectId::class.java) { notifier.notifyUser(User(INCORRECT_ID, "Mike", "Bull")) } } @Test fun `It is expected that notifyPerson will return true to indicate success`() { val notifier = FakeNotifier(initialized = true) assertThrows(IncorrectId::class.java) { notifier.notifyUser(User(INCORRECT_ID, "Mike", "Bull")) } } @Test fun `Function should check if notifyPerson returns true as expected in correct conditions`() { val notifier = FakeNotifier(initialized = true) val id = 123 notifier.incorrectImplementationMakingNotifyPersonReturnFalse = true assertThrows(AssertionError::class.java) { notifier.notifyUser(User(id, "Ben", "Barack")) } } class FakeNotifier(initialized: Boolean = false): Notifier { override var initialized = initialized private set var usersNotified = setOf<Int>() var incorrectImplementationMakingNotifyPersonReturnFalse = false override fun checkId(id: Int): Boolean = id != INCORRECT_ID override fun notifyPerson(id: Int): Boolean { if(incorrectImplementationMakingNotifyPersonReturnFalse) return false usersNotified = usersNotified + id return true } } companion object { const val INCORRECT_ID = -100 } }