Have been trying to do some testing on a place whe...
# apollo-kotlin
s
Have been trying to do some testing on a place where I’m also using an ApolloClient + QueueTestNetworkTransport + test builders + parameterized tests, and got a question mostly for how to work with the test builders here. The real code is here, but the gist of what I am not finding a way to make it work nice is that I want my parameterized input to be a map of
SomeType -> ExpectedResult
. and then I need to somehow make that work with the test builder. The test builder doesn’t take in the type itself, since it uses its own DSL, so I am doing something silly like having my parameter be of the type I actually want to get from the apollo call, and then I map it to the
buildBlahBlah
that I need, like
Copy code
FooQuery.Data {
  status = when(parameterizedInput) {
    1 -> buildBlah {}
    2 -> buildOtherBlah {}
  }
}
But it’s quite inconvenient I think, I wonder if there’s something better I can do here.
Hmmm actually I couldn’t get it to work before, but doing this also works
Copy code
override fun provideValues(): List<Pair<BuilderScope.() -> ContractStatusMap, IsAllowedToTerminateContract>> {
  return listOf<Pair<BuilderScope.() -> ContractStatusMap, IsAllowedToTerminateContract>>(
    { it: BuilderScope -> it.buildPendingStatus {} } to IsAllowedToTerminateContract.ALLOWED,
  )
}
The trick is that in the lambda I am creating, inference does not just work and I need to very explicitly say that the receiver inside the lambda is of type
BuilderScope
with the
{ it: BuilderScope ->
part which I’ve never had to do before I think. This gives it access to the buildFoo() function, otherwise it was just red even if I explicitly set the type in the
listOf<>()
call. Very very interesting. I think this is the way to go then, my parameterized input can be a lambda which I can use inside the builder. Just a bit tricky to get that lambda right, but it does work 😅
b
Ah interesting! I was gonna say, maybe something with the parameters being a lambda, but not exactly sure how/what 🙂
s
Yeah I tried this initially, but it just wouldn’t let me resolve the function, so I figured it wouldn’t work. But this does, while looking super odd tbh with the explicit type there 😅 I thought it’d be able to pick that up from the fact that the list is explicitly typed with the
BuilderScope.() -> ContractStatusMap
but no, the lambda does not see
BuilderScope
in there unless I explicitly put it there with
it: BuilderScope ->
b
a bit odd indeed 🙂
I guess sometimes the compiler needs a little help 😅
😅 1
b
actually I'm confused, shouldn't it be
BuilderScope -> ContractStatusMap
instead of
BuilderScope.() -> ContractStatusMap
?
s
It’s a function lambda, so it either has to be
BuilderScope.() -> ContractStatusMap
or
(BuilderScope) -> ContractStatusMap
right? In either case, the compiler can use either one of them interchangeably in this context as far as I can tell. It’s just that in the lambda itself I can’t somehow denote that it’s
BuilderScope.() -> ContractStatusMap
so I pass it as
it
which would mean that it’s like
(BuilderScope) -> ContractStatusMap
yeah. But yeah, it knows how to figure out “`T.() -> Unit` <-> `(T) -> Unit`” by itself.
Magic 🪄
Isn’t it perhaps somewhat related to how on the JVM they got the same (I think?) signature? I think extension functions when called by Java callers you simply pass the receiver as the first parameter and it works right?
b
Woops you're right, I meant
(BuilderScope) -> ContractStatusMap
But still something I don't get, e.g.
Copy code
val lambda1: (String) -> Int = { it: String -> it.toInt() }
val lambda2: String.() -> Int = { it: String -> it.toInt() }
lambda2 doesn't compile for me
but:
Copy code
val listOfLambda1 = listOf<(String) -> Int>({ it: String -> it.toInt() })
val listOfLambda2 = listOf<String.() -> Int>({ it: String -> it.toInt() })
does compile. 🪄 indeed
s
Haha yeah that’s a bit crazy is it not 😅 And you do also see that if you do not add the
it: String ->
there you do not get the
String
as a receiver in the lambda right?
b
in my case
Copy code
val listOfLambda2 = listOf<String.() -> Int>({ this.toInt() })
also compiles
but we probably stumbled on a quirk :)
something for those "Kotlin Puzzlers" talks 😄
s
“Puzzled” is definitely an adjective that describes me right now yeah 😅
😂 1