-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Move LocationFactory to plugins to allow overriding it #3063
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #3063 +/- ##
============================================
- Coverage 85.45% 85.45% -0.01%
- Complexity 2888 2889 +1
============================================
Files 329 329
Lines 8801 8811 +10
Branches 1093 1093
============================================
+ Hits 7521 7529 +8
- Misses 992 993 +1
- Partials 288 289 +1 ☔ View full report in Codecov by Sentry. |
dba1f01
to
be64f3f
Compare
Yes this is an area where we have not yet figured out how we should solve this. One question I have before we analyze the various options: are you sure that on the slow path you are using the Stackwalker? We have seen significant improvements when that's used, to the extent that the requests for improved performance mostly were gone. |
Yes, StackWalker is used on the slow path, I also just tested it with the Java 8 Location implementation and there it is even worse with 4 minutes and 44 seconds. StackWalker: 1 min 58 sec |
Bumping this. Without some way to disable this, mockito is an order of magnitude more expensive than a simple Java proxy |
I do think this is a legitimate issue to be fixed, but I am unsure whether this is the best way to solve it. Ideally, I would like to explore how to best integrate this with CI/IDE tooling, so that they can take advantage of this. E.g. in case a test passes, we don't need all of this information. But when a test fails, we do need this information. I can imagine a workflow where a test fails, on rerun we want more explicit information. And on CI I can imagine that we want the full stacktrace, to ease debugging. By making it overridable, we do have the building blocks, but the way to use it is not straightforward. Similar to what we have done with Given this feature, in which scenarios do you think it is worthwhile to drop the location information, keeping in mind we have to balance performance and debuggability in for example CI environments? |
Pretty much all local tests on my IDE, if they fail and need the location information to debug that, then I can re-enable as necessary. The location information takes the time for certain tests from seconds to minutes |
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.
Given that this is predominantly useful when builds fail and there is benefit of a run-twice scenario, I wonder if we should write a Gradle/Maven plugin for this. What I am thinking is that, similar to the Gradle retry plugin, we can instruct Mockito to run without location on a first run. If a test fails, we can enable location data when we run that test and try again.
This means that we make it configurable per test invocation. The plugin should then generate a LocationFactory
that can be used while running the test.
While I am typing this, I realize that integrating a pre-defined LocationFactory
at runtime into a test invocation might not be possible. I don't know whether it is possible to change System properties on the fly, but maybe that is the better route after all?
Basically, I don't want this to become the default, as it significantly increases debugging efforts when dealing with failures. But for passing tests, these kind of optimizations make a lot of sense to me. Hence my thought process for retry, where you benefit from the speedup for all passing tests and then for failures it can become more descriptive. Since it is opt-in with a plugin, the default experience of Mockito remains correct. And for super slow tests, the correctness is probably more important than for fast tests.
/** | ||
* Describes the location of something in the source code. | ||
*/ | ||
@NotExtensible |
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 think we want to make this part of an extension point for external users. E.g. while Mockito is allowed to implement such interfaces, we don't want external users to implement them. Therefore, let's remove this here and create a utility function that can create a Location based on a SourceFile
?
This sounds definitely interesting, how would you like to taggle this? Should I make a PoC? or what is the process in Mockito for such things? Something which also maybe worth looking into is a JUnit 5 extensions, since it is possible to intercept the method invocation it may be possible to call the test twice if it fails, although here it is harder to handle cleanup stuff. |
Before we invest a lot of time into writing such a plugin, let's first design it to see what is possible. Some initial thoughts/questions:
|
I have a very similar situation and would like to see some type of change to enable the squashing of the reporting the location. I'm wondering if this approach / some of the options might be over-engineering this problem. In my particular use-case, I only really care about squashing the location for a specific mock that my test interacts a lot with. I (largely) do not care on any of the other mocks and fine with the performance hit. Because of this, I think it might make sense to implement this feature via the
and then in MockMethodAdvice#advice, the mock settings could be checked to determine whether to report the actual location.
|
Looking at this further, I think it is actually incorrect to be collecting the real Location on stubOnly mocks. As far as I can tell, Location is only reported when a verification fails. With StubOnly mocks, mockito already throws an exception when attempting to verify on a stub only mock, so I don't think it is possible to get mockito to report these locations OOTB and collecting these locations is wasting resources. This approach has the added benefit of still supporting calls into LocationFactory when a user could fail a verification check and would want to report the location. This also does not affect the reporting of I suspect that in many of the situations that a user is interacting with a mock millions of times the mock is going to already be a StubOnly mock because of the memory issues of tracking millions invocations. |
As part of a rework on a project I'm contributing to, Mockito was added to replace the use of InvocationHandler.
One particular test class validates the behavior of around 1000 objects, with each other, resulting in a particular set of code running over 1 million times, using the mock a few times in the process. This results in the mock object being used over 15 millions times.
Oversimplified current use:
Resulting in the execution time of this particular test class to rise from a few seconds to over 2 minutes. After some profiling, we found that a huge part is caused by Mocktio's Location feature.
This PR moves the LocationFactory over to plugins, to allow others to override it. Which in our case we would use to return a dummy empty Location. Using a dummy Location reduced the execution time of our test class to under 1 minute. And after some other changes in our code base, not related to this PR, to around 20 seconds (which will it is not a few seconds as before, is much better than 2 minutes).
Will we understand and are thankful that Mockito wants to provide helpful error messages, in our particular use case we would like the faster testing time, so that this test can also be easily run during normal development. If the need for Location information arise, we could still just remove the extension and run it slower for a particular time.
Looking at some GitHub issues and PR, such as #2723 which also wanted to add a system property to use a dummy Location, it seems we are not the only one which would benefit from such an extension option.
Checklist
including project members to get a better picture of the change
commit is meaningful and help the people that will explore a change in 2 years
Fixes #<issue number>
in the description if relevantFixes #<issue number>
if relevant