How to write unit tests when a private variable is used in all public functions?

182 views Asked by At

I have a function named LoginInteractor.java like this:

public class LoginInteractor {

    private LoginSessionManager loginSessionManager;
    private static LoginInteractor instance;

    public static LoginInteractor getInstance() {
        if (instance != null) {
            return instance;
        }
        instance = new LoginInteractor();
        return instance;
    }

    private LoginInteractor() {
        loginSessionManager = LoginSessionManager.getInstance();
    }

    public boolean isLoggedIn() {
        return loginSessionManager.isLoggedIn();
    }

    public Intent getLoginIntent() {
        return loginSessionManager.getLoginIntent();
    }
}

and another class LoginSessionManager.java like this:

public class LoginSessionManager {

    private LoginManager loginManager;
    private LogoutInterface logoutInterface;
    private static LoginSessionManager loginSessionManager;

    public static LoginSessionManager getInstance() {
        if (loginSessionManager != null) {
            return loginSessionManager;
        }
        loginSessionManager = new LoginSessionManager();
        return loginSessionManager;
    }

    private LoginSessionManager() {
        loginManager = LoginManager.getInstance();
    }

    public boolean isLoggedIn() {
        return LoginManager.getInstance().isLoggedIn();
    }

    public Intent getLoginIntent() {
        return loginManager.newLoginIntent();
    }

    public Intent getLogoutIntent() {
        return loginManager.newLogoutIntent();
    }
}

I'm writing unit tests for the class LoginInteractor in LoginInteractorTest.kt and this is how I have written unit tests for two functions.

@RunWith(PowerMockRunner::class)
@PrepareForTest(
    UserInteractor::class,
    TextUtils::class,
    LoginInteractor::class,
    LoginSessionManager::class
)
class LoginInteractorTest : TestCase() {
    @Mock
    private lateinit var loginInteractor: LoginInteractor

    @Mock
    private lateinit var loginSessionManager: LoginSessionManager
    
    @Throws(Exception::class)
    public override fun setUp() {
        MockitoAnnotations.openMocks(this)
        Whitebox.setInternalState(LoginSessionManager::class.java, "loginSessionManager", loginSessionManager)
        Whitebox.setInternalState(LoginInteractor::class.java, "instance", loginInteractor)
    }

    @Test
    fun isLoggedInTest(){
        `when`(loginSessionManager.isLoggedIn).thenReturn(true)
        assertEquals(true, loginInteractor.isLoggedIn)
    }

    @Test
    fun getLoginIntentTest(){
        `when`(loginSessionManager.loginIntent).thenReturn(Intent())
        assertNotNull(loginInteractor.loginIntent)
    }
}

Both of them are failing. For the first one, it says expected is true, but actual is false and for the second unit test, it says AssertionError

I suspect that the problem is when creating an instance of LoginInteractor, loginSessionManager variable is initialised in its private constructor. But when we say WhiteBox(...LoginSessionManager...), this is a completely different object.

How to resolve this issue and make the unit tests run perfectly.

0

There are 0 answers