-
Notifications
You must be signed in to change notification settings - Fork 2
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
Pass exceptions on to manufacture method #107
Conversation
Also, chained assertions. Refs: #106
@@ -120,6 +124,17 @@ void fallbackToFactoryMethodWhenConstructorThrowsException() { | |||
assertThat(result.getValue()).isNotNull(); | |||
} | |||
|
|||
@Test | |||
@DisplayName("will fallback to factory method and pass exceptions on") |
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.
This name is a bit misleading, because the class used in this test does not have a factory method.
If it had one and the factory method would succeed, then no exception would be thrown.
If it had one and the factory method would also throw an exception, the test is still green because the stack trace is the same (because we swallow the factory method exception here).
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'm not quite sure I understand.
The test-class does not have a factory-method intentionally - because it wouldn't throw otherwise. Yet we still fall back to a factory-method, because everything else failed.
So the intention is to have all approaches fail (the factory-method approach being the final one) and display the entire stack to show what we tried.
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.
This test checks what happens if the constructor fails and the object has no factory method.
I would expect a different stack trace if a factory method was found but could not be successfully called because it also throws an exception.
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.
This test checks what happens if the constructor fails and the object has no factory method.
Correct!
I would expect a different stack trace if a factory method was found but could not be successfully called because it also throws an exception.
Me, too. But this is not what the test is supposed to test. Are you saying there is a test missing?
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.
Yes. We currently have no test for the unlikely case where a constructor method throws an exception and a factory method also throws one.
The more I think about it, the less I think this is ever going to be a problem.
We might just wait until someone files a bug report.
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 added the test.
This is the exception we would now get:
To me, the What we are trying to tell the caller is that we found neither a public constructor nor a factory method (and the order in which we looked for them should not be important). So while I really like the whole logic in this PR, I suggest we look for a better stack trace (maybe just one message?). |
Any suggestions? I'm aware that blowing up the stack trace is not perfect, but it seemed the easiest and quickest way to achieve the task. |
return random.shuffled(type.getDeclaredConstructors()) | ||
.stream() | ||
.filter(x -> Modifier.isPublic(x.getModifiers())) | ||
.findFirst() | ||
.map(x -> construct(type, x, customizationContext)) | ||
.orElseGet(() -> manufacture(type, customizationContext)); | ||
.orElseGet(() -> manufacture(type, customizationContext, new SpecimenException("No public constructor found"))); |
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.
We should add the name of the class for which no public constructor was found. It could be that this is not the class I am fixturing but one of its fields.
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.
Good point!
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.
And if we add something like "trying factory methods next" to the message, it would improve the understandability of the stack trace.
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 we should not do exceptions at all and implement proper strategies?
I mean, this can certainly be improved. But do you think this is mergeable as a first attempt with improving it on further iterations?
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.
Long comment short: Yes, I think we should try it.
Let's label it as experimental because it will only affect diagnosis, not behaviour.
I am putting on my user hat: With that in mind, the current PR gives me an answer to that. That is good. As a developer of JavaFixture I am happy that I have all three exceptions. It helps me understand where any future bugs might come from. As user of JavaFixture that is more than I need, but maybe this is a good compromise. |
We may randomly create two Options.empty objects which are the same, so we cannot check if we cached any of these.
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.
fix: flaky test
Good catch, thank you!
Refs: #106