0

The application in question has a logout function that among other things, performs a call to CookieManager.getInstance().removeAllCookies(null):

fun logout(...) {                                                                           
    showLoader(true)                                                          
                                                                                                                                                    
    msgRepo.unregisterSendBirdHandlersAndPushToken(                           
        onSuccess = {                                                         
            clearUserData(...)
            // ...                                       
            onLogout()                                                        
        },                                                                    
        onFailure = {                                                          
            clearUserData(...)
            // ...                                       
            onLogout()                                                        
        }                                                                     
    )                                                                         
}                                                                                                                                                    
                                                                              
/**                                                                           
 * Helper to clear user data before logging user out                          
 */                                                                           
private fun clearUserData(...) {                                                                           
    // ...                                            
    CookieManager.getInstance().removeAllCookies(null)
}                                                                             

Two tests reference the aforementioned logout function. They both are quite similar and look a bit like this:

@Test                                                              
fun `verify logout with success`() {                               
    // .. Other code                                                             
    HardLogoutHelper.logout(...)                                                              
    // ...                            
}                                                                  

The tests fail with the following error message:

'void android.webkit.CookieManager.removeAllCookies(android.webkit.ValueCallback)' java.lang.NoSuchMethodError: 'void android.webkit.CookieManager.removeAllCookies(android.webkit.ValueCallback)' at com.example.helpers.HardLogoutHelper.clearUserData(HardLogoutHelper.kt:86)

I've tried running the test with Roboelectric via @RunWith(RoboelectricTestRunner::class) and I have have tried creating a custom Roboelectric Shadow for the CookieManager class. The issue seems to persist even when using Roboelectric.

Why is the previously mentioned error message being thrown, and how can it be fixed?

Orbit
  • 2,985
  • 9
  • 49
  • 106
  • Perhaps this class should not be referencing `CookieManager` directly. Instead, have it work with some custom interface. In production, you would have your dependency inversion framework (Dagger/Hilt, Koin, etc.) supply an implementation of the interface that uses `CookieManager`. In a unit test, your test code would supply an implementation of the interface that is a fake or other type of test double. – CommonsWare Jan 09 '23 at 19:19
  • The `logout` function is actually not in a traditional class but in a Kotlin `object` called `object HardLogoutHelper`. The `HardLogoutHelper.logout` function could certainly be rewritten to take a `CookieManager` argument, but then every place where `logout` is invoked would require a `CookieManager` instance. – Orbit Jan 09 '23 at 20:47
  • "but then every place where logout is invoked would require a CookieManager instance"' -- I recommend that you look into using dependency inversion frameworks (Dagger/Hilt, Koin, etc.). – CommonsWare Jan 09 '23 at 20:55
  • The app does use Dagger. I simply don't want to pass along a dependency (i.e. provide a `CookieManager` instance to every place that may eventually call `HardLogoutHelper.logout`) through so many channels if there is a simpler solution for fixing the test. – Orbit Jan 09 '23 at 21:04
  • If you inject `HardLogoutHelper`, you do not need to also inject a `CookieManager` -- Dagger can supply the `CookieManager` to `HardLogoutHelper`. – CommonsWare Jan 09 '23 at 22:20

0 Answers0