Hey guys, I'm running out of ideas; I need help. I...
# plugin-development
s
Hey guys, I'm running out of ideas; I need help. I have a custom task (created within a plugin) that creates an object (some kind of
HttpClient
) and then calls some function of this
HttpClient
. Right now I put the
ApiToken
(String) into the task and created the HttpClient in the
TaskAction
function. Now I want test this with TestKit. Obviously, I don't want to test the real
HttpClient
call and want to fake it. For this I thought I can add the
HttpClient
as a
Property<HttpClient>
to the task and use it as
@Internal
. But with that approach the configuration cache fails.
cannot serialize object of type 'kotlinx.coroutines.scheduling.DefaultIoScheduler', a subtype of 'java.util.concurrent.Executor', as these are not supported with the configuration cache.
.. And more
I also once created a custom
BuildService
to
@Inject
the
HttpClient
. But this also didn't worked as expected because in test I couldn't apply my plugin because this would create a real instance of the
HttpClient
. Not applying the plugin failed because for some reasons my source code was not added to the test classpath if I don't apply the plugin (sounds weird, but this was the case 🤷 ). Therefore I couldn't use any classes of my plugin... Reading about this a bit more I came to the conclusion that my question might be way more general: How to add a custom object to a Task that works with the configuration cache 🙈 Seems that right now the best solution is to create an BuildService for these cases..? But this sounds a bit wrong to me... 🤔 🤷 Appreciate any help here!
v
To work with CC, all task properties need to be serializable in the sense Gradle expects it to. If
HttpClient
is not at least Java serializable, you cannot have it as a task property to be compatible with CC. You could for example in the task create real or fake http client depending on some boolean. Or you could maybe use some mocking framework that can mock all instances of
HttpClient
. Or you can maybe indeed have some kind of producer that generates either or the other like a build service, ... Not sure how the best option would be here from the top of my head.
🚀 1
s
Or you can maybe indeed have some kind of producer
But this producer also has to be compatible with Gradle somehow, right? 🫠
v
Of course, but depends on how you use it. If it for example has some static "give me http client" method that is only used at execution time, it should just work. If you create an instance and set it as property of the task, it of course has to follow the rules again that it can be serialized into the CC. ...
👍 1
s
Alright, thanks for far @Vampire 🙂
Well, seems that an Singleton (Kotlin
object
) should do the trick:
Copy code
interface HttpCreator {
    fun createHttpClient(token: String, projectId: String): HttpClient
}

object X : HttpCreator {
    override fun createHttpClient(token: String, projectId: String): HttpClient =
        DefaultHttpClient(token, projectId)
}
...
Copy code
@get:Internal
    abstract val httpCreator: Property<HttpCreator>
🫠 Let me accept this as a solution for now 😂
👌 1