Just got bit by a mistake in testing which I seem ...
# apollo-kotlin
s
Just got bit by a mistake in testing which I seem to be repeating quite often and I want to confirm that there is nothing better I can do here besides being more careful. We have two mutations in this shape:
Copy code
memberUpdateEmail(input: MemberUpdateEmailInput!): MemberMutationOutput!
memberUpdateLanguage(input: MemberUpdateLanguageInput!): MemberMutationOutput!
notice the same response type on both of them. I was writing some tests, and I was enqueuing some responses like this:
Copy code
apolloClient.registerSuspendingTestResponse(
 MemberUpdatePhoneNumberMutation(newPhoneNumber),
 MemberUpdatePhoneNumberMutation.Data {
  this.memberUpdatePhoneNumber = this.buildMemberMutationOutput { ... irrelevant what's in here }
 },
)
apolloClient.registerSuspendingTestResponse(
 MemberUpdateEmailMutation(newEmail),
 MemberUpdateEmailMutation.Data {
  this.memberUpdatePhoneNumber = this.buildMemberMutationOutput { ... }
 },
)
And I could not for the life of me figure out why my tests were failing but it was all here
Copy code
MemberUpdateEmailMutation.Data {
 this.memberUpdatePhoneNumber = this.buildMemberMutationOutput { ... }
},
Which should have instead been
Copy code
MemberUpdateEmailMutation.Data {
 this.memberUpdateEmail = this.buildMemberMutationOutput { ... }
},
Notice the difference in which field I am defining in the lambda there? And there was no type-safety related error kicking in here since they both happen to accept the same response type, so it was compiling just fine. Lmk if what I say is clear enough or not 🤗
m
The type safety is generally really hard to do because it would mean generating models based on the JSON response and due to the expressivity of GraphQL, this may generate code that grows exponential with the number of fragments
We initially wanted to do that for v3 but that ended up being way too expensive and we ultimately reverted
Other languages (TypeScript) manage to get this working in practice, I think because the types are completely erased at runtime so it's more lightweight.
But in Kotlin, I've been turning this problem around for the past years but don't have a great solution so the tradeoff is to build data based the schema (and therefore lose some type safety)
s
Yeah, I don't blame you whatsoever for this not being perfect, I've seen many discussions here and I do understand why this is hard and does not have a perfect solution. I just wanted to make sure I am not missing any other trick I could be doing here, and I think that I am not. I should simply try to be more careful when working with generating these data objects. And there's nothing which could warn me that I am trying to populate a field in the response that normally has nothing to do with the query data I am actually trying to build there, inside the
.Data { }
lambda, right? The alternative of going down to MockServer would make everything even less type-safe as far as I understand, since then it'd be a matter of hand-writing JSON responses, so I wouldn't be gaining anything by looking there either.
m
We should add support for strict mode actually. This was an issue opened a very long time ago that I completely forgot about that would could at least detect this issue
s
Oh absolutely, that would be exactly what would help me here. It'd be okay to not be a compile time issue even, but if some error told me that I am populating irrelevant data in the first place I would have immediately realized my mistake! I've subscribed to the issue to keep track of if there's any movement 😊
m
Thanks for the reminder to look into this!
blob hug 1