-
Notifications
You must be signed in to change notification settings - Fork 4
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
[DSDK-183] [TS] [DSDK] Error/Type safety with purify-ts #12
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
883dc5c
to
a55205c
Compare
edit: FIXED |
const parseResponseSpy = jest.spyOn( | ||
RestRemoteConfigDataSource.prototype as any, | ||
"_parseResponse" | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[ASK] if we spy on a private class methods to check the method calls of RemoteConfigDataSource
, does this class respect the single responsibility principle?
Shouldn't it be splitted with a Repository class?
@mbertin-ledger @smartine-ledger
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point is not the SRP but the Unit Test best practice : a private method must not be tested. To be honest I am not sure to understand why we try doing that 👍 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so we can have all the different state during the tests (good json, bad formatted json, bad api call etc...).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case this should be tested through RemoteDataSource.getConfig()
(not by calling private methods)😉 . A UT tests what is exposed by your classe (= public / internal methods). Nothing more
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But the coverage tho....
also we are not testing those private functions, we just make them behave differently so .getConfig()
can throw all the possible cases (Error or Success). It would be the same as mocking a fetch or api call.
There is also a test that just run them vanilla so we do go through them "privately".
This way I get into all the different branches of my code and get a 100% coverage on what I've developed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not have a good understanding when testing in JS/TS. We may need to discuss about that with the team. During a continous improvment? 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah we should talk about it - I don't think we can reach 100% everywhere. There is probably a layer (the outermost layer in the clean archi) that we won't be able to unit tests without doing some stuff like spying, because what they use is not dependency injected into them.
In the example of RemoteConfigDataSource
, we could dependency inject an interface representing the fetch
/axios
api, so we can mock them without using "spy". But they will probably be cases where it's not practical
08a38b4
to
b40877a
Compare
packages/core/src/internal/config/data/RemoteConfigDataSource.test.ts
Outdated
Show resolved
Hide resolved
export type RemoteConfigFailure = | ||
| ApiCallError | ||
| ParseResponseError | ||
| JSONParseError; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't mind, but so in our architecture/module structure we should put the error types definitions inside the di
folder ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where would you put them ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe in the model
or data
folder ? Because they are about the model Config
? But i don't have a strong opinion, i'm asking to know where i should put my errors definitions too ahah
caed192
to
4623e40
Compare
); | ||
return JSON.parse(version) as Config; | ||
getConfig(): Either<LocalConfigFailure, Config> { | ||
return Either.encase(() => stubFsReadFile()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh encase
seems super practical
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great addition, Purify is going to be super useful !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
📝 Description
Following the PoC and study about using a potential FP library in the project, here is a rewrite of the
module
that ship error safety using purify-tsThe interesting part of this is how we can handle easily the different types of error and at which point we do this.
From what I could see during the implementation of this, the Either (aka Result) and Maybe (aka Option) helpers will be mostly used by the data sources as it might not be safe getting
value from these external sources. The Either and Maybe are handled in the services, and the usecase never knows about these types.
Let's see how we manage to tame this tool into the library: it does make things a little more verbose, however the error/type safety is pretty amazing.
❓ Context
✅ Checklist
Pull Requests must pass the CI and be code reviewed. Set as Draft if the PR is not ready.
[ ] Impact of the changes:
🧐 Checklist for the PR Reviewers