Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Mocking notifications #26

Open
afollestad opened this issue Jan 3, 2019 · 3 comments
Open

Proposal: Mocking notifications #26

afollestad opened this issue Jan 3, 2019 · 3 comments
Labels
enhancement New feature or request

Comments

@afollestad
Copy link

afollestad commented Jan 3, 2019

In apps I tend to give notification creation responsibility to injectable interface that has a "Real" implementation. The interface is mocked in my tests.

I could see this being a very big use case for this library in addition to the already great convenience. Since you're using Kotlin, this could just be an companion object extension that could be a testImplementation dependency. Something like:

Notify.withMock(context)
   ...
   .show()

Internally, it would use Mockito or some internal class that isn't the real Android framework class.

@Karn
Copy link
Owner

Karn commented Jan 4, 2019

This sounds like a great idea -- though I'm a little unsure about what the implementation would look like (My mocking knowledge is a little limited). Perhaps you can clarify or provide an example library which uses such an extension function?

It seems that you would have to use the .withMock(context) to differentiate between a real implementation and a mocked implementation. Does this not mean that you would have to have some sort of provider which wraps all the Notify.with(context) calls to automatically give you the correct instance of the library? Or is the assumption that the function call to build and show a notification is self-contained and we simply want to swap out this self-contained chunk with the corresponding mocked chunk?

@Karn Karn added the enhancement New feature or request label Jan 4, 2019
@afollestad
Copy link
Author

I could definitely contribute if you'd like 😄

Since you have:

class Notify {
    companion object {
        fun with(context: Context): Notify {
            ...
        }
    }
}

You could have another module, a test module, that declares something like this:

fun Notify.Companion.withMock(context: Context): Notify {
    ...
}

I was thinking you could integrate with Mockito like this:

fun Notify.Companion.withMock(context: Context): Notify {
    return Mockito.mock(Notify::class.java)
}

However that wouldn't be automated and would require usage updates. So it would be nice if the existing with method could do this automatically, internally.

Maybe there could be some sort of global property that would be set when a unit test or UI test is beginning to run. With that property set to true, the existing with(Context) method could know to switch out the real implementation with a mock implementation.

@Karn
Copy link
Owner

Karn commented Jan 5, 2019

I'm always taking new contributions! Your proposal makes sense to me and I think I would be very beneficial. If you can throw up a PR I can take a look and we can get it merged in.

Turns out that the if we want to mock the NotificationManager as well, we can simply supply the mocked instance as follows (provided that we are scoped in test sources due to the restriction imposed by the internal access modifier):

Notify.defaultConfig {
    notificationManager = mockNotificationManager
    ...
}

As long as this step is done during initialization, i.e prior to the first use of Notify.with(...), the mocked instance of the Notification Manager will be used. This takes care of external APIs that might need to be mocked.
Finally, I think the best solution would be to use a withMock(...) extension function, I would prefer not to add test specific conditional logic to the with(...) function.

Let me know what you think!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants