Skip to content

Test Double ‐ Fake

Devrath edited this page Oct 24, 2023 · 2 revisions

github-header-image

Observation

  • A fake is more close to a real implementation but a simplified version
  • Using a fake, We can change the functionality and provide our own implementation to satisfy the requirement.
  • Then provide a fake class instead of a real class.

Usage examples

  • Another example can be instead of connecting to a remote, We connect to a local server and return the same data.
  • Instead of storing the data in shared-prefs we keep a local copy of it and get it back.
  • Because of this classes that use this implementation end up working without breaking.
  • Most of the time when we are using the REST-API, We end up using fakes.

How fakes are different from mocks

  • When using mocks, When the production code changes there needs to be changes in the test code as well
  • But when we use fakes, We just need to visit the fake class and modify the changes, and no need to change the test class

Important points

Be mindful not to modify the fakes while testing

  • Say you have built the fake and have passed the fake to a class-implementation, Now we need to use the class-implementation-instance to modify or call the functionalities and not the fake class that is used.
  • So our focus is the SUT.

Code

Cache.kt

data class Cache(val isChacheEnabled : Boolean)

LoginService.kt

interface LoginService {
    fun connectToServer()
    fun makeConnection() : Cache
    fun disconnectFromServer()
}

LoginServiceImpl.kt

open class LoginServiceImpl : LoginService {
    override fun connectToServer() { }
    override fun makeConnection(): Cache {
        if(someCustomImplementation()){
            return Cache(isChacheEnabled = true)
        }
        else{
            return Cache(isChacheEnabled = false)
        }
    }

    override fun disconnectFromServer() { }

    private fun someCustomImplementation(): Boolean {
        // Some implementation logic
        return true;
    }
}

LoginServiceImplFake.kt

class LoginServiceImplFake : LoginServiceImpl() {
      override fun connectToServer() {
        super.connectToServer()
    }
    override fun makeConnection(): Cache {
        super.makeConnection()
        return CustomFakeImplementationForServerSideChanges()
    }

    override fun disconnectFromServer() {
        super.disconnectFromServer()
    }

    private fun CustomFakeImplementationForServerSideChanges(): Cache {
        // Some other implementation -> Caused due to changes from the external service
        return Cache(isChacheEnabled = true)
    }
}