ably-java icon indicating copy to clipboard operation
ably-java copied to clipboard

Public Final Properties Make It Hard To Test

Open benwaine opened this issue 5 years ago • 3 comments

I'm trying to write a test to ensure that my code is using the Ably SDK correctly however the public final channels property is final and there is no accessor method. This makes mocking the channels object impossible.

Example:

    fun handle(message: String) {

        // Extract Key Fields From Message (name, userId) used to forward message to correct channel
        // Note: Not extracting "payload" from json which changes for different values of $.name
        val json = Configuration.defaultConfiguration().jsonProvider().parse(message)
        val messageType = JsonPath.read<String>(json, "$.name")
        val userId = JsonPath.read<Int>(json, "$.userId")

        // Use SDK to publish to channel using the event name
        client.channels.get(userId.toString())
                .publish(messageType, message)
    }
internal class AblyHandlerTest {

    val mChannels = mock<AblyBase.Channels>()
    val client = mock<AblyRest>()
    val handler = AblyHandler(client)

    @BeforeEach
    fun before() {
        // Does not exist - now impossible to write the test below
        whenever(client.getChannels()).thenReturn(mChannels)
    }

    @Test
    fun `it uses the name and user id to correctly route the message`() {

        val rawMessage = """
            {
                "name": "UserUpdatedEvent",
                "userId": 42,
                "payload": { "nested": "data" }
            }
        """.trimIndent()

        handler.handle(rawMessage)

        verify(mChannels).get("42")
    }
}

I'm 100% TDD and so this break in encapsulation feels a bit jarring, any chance of getting the accessor methods added?

Thanks!

┆Issue is synchronized with this Jira Task by Unito

benwaine avatar Feb 12 '20 12:02 benwaine

Hello @benwaine - thanks for submitting this request and apologies for not responding sooner. This is something that we would like to improve soon as you're not the first person to mention it.

QuintinWillison avatar Feb 27 '20 12:02 QuintinWillison

Yes, we're facing the same issues. Everything nicely tested, expect the Ably part... Would make a nice (and straight forward?) addition to the project.

tvschuer avatar Oct 12 '20 12:10 tvschuer

For visibility: this issue has been reported again and we've found that the following workaround using Spring can be used in this instance to allow reflection on AblyRest.channels. Obviously the real solution here is to refactor the library itself but this should suffice as a hacky workaround for the time being.

AblyBase.class.getDeclaredField("channels").setAccessible(true);
ReflectionTestUtils.setField(ablyRest, "channels", mockChannels);

owenpearson avatar Mar 31 '21 15:03 owenpearson