Often when testing software we want to construct an object which is dependent on other objects or functions, but we know that this code dependency is not a concern of our test. In these situations it is nice to use the simplest possible test double, classified by Gerard Meszaros as a dummy. If this double is an object with member functions (also known as methods), none of these functions will be implemented. It might look something like this:

For a given interface of FileStorage

interface FileStorage {
    fun listFiles(): List<FileName>
    fun downloadFile(name: FileName): File
    fun uploadFile(file: File)
}

a basic dummy might be

object DummyFileStorage : FileStorage {
    override fun listFiles() = TODO("not implemented")
    override fun downloadFile(name: FileName) = TODO("not implemented")
    override fun uploadFile(file: File) = TODO("not implemented")
}

In other test situations we might want other types of test double. These could be stubs, spies, fakes or mocks, depending on the style of testing we deem appropriate. It is quite common that we might need for example, a stub, but our test is only concerned with one member function. We can duplicate the dummy and give only this function the implementation we desire, but this can lead to a lot of code duplication, especially if we have complicated objects (not that complicated objects are desirable, but I’m sure we’ve all been in this situation). If we are testing a collaborator of FileStorage who calls the listFiles function, a basic stub for our FileStorage interface might look like this:

class StubFileStorage(fileNames: List<FileName>) : FileStorage {
    override fun listFiles() = fileNames
    override fun downloadFile(name: FileName) = TODO("not implemented")
    override fun uploadFile(file: File) = TODO("not implemented")
}

Kotlin provides us with a nice way to extend the dummy object and remove the noise. If we replace our dummy object with an open class

open class DummyFileStorage : FileStorage {
    override fun listFiles() = TODO("not implemented")
    override fun downloadFile(name: FileName) = TODO("not implemented")
    override fun uploadFile(file: File) = TODO("not implemented")
}

we can now extend the dummy, and only stub the function we care about:

class StubFileStorage(fileNames: List<FileName>) : DummyFileStorage() {
    override fun listFiles() = fileNames
}

If the usage is isolated to one particular area of our code, and we don’t need any constructor parameters for our stub, we can even inline it as an anonymous object and assign it to a variable:

val stubFileStorage = object : DummyFileStorage() {
    override fun downloadFile(name: FileName) = File()
}

I’m not sure where this pattern originated (I think I was first shown it by Dmitry Kandalov or Priyo Aujla) but I don’t see it in use much and I think it’s quite useful.

Test doubles explained by Martin Fowler: Mocks Aren’t Stubs

Test double definitions by Gerard Meszaros: Mocks, Fakes, Stubs and Dummies