-
Notifications
You must be signed in to change notification settings - Fork 469
Spying on Spys does not work properly #1029
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
Comments
I don't quite get the use-case for spying on spies to be honest. I don't think that we will "fix" something here, as it is quite the edgecase and the verification could be handled in the first interaction. Spies should be avoided if possible, as is noted in the docs.
|
This is a very simplified example with which you can reproduce the issue and not the real-world example. In the meantime I pushed my project, so you can have a look at the real-world example, currently of course with the work-around I described: https://github.com/Vampire/command-framework/blob/eb87c56da8f46b6886d8411a74de11a71ba8f174/src/test/groovy/net/kautler/command/api/CommandHandlerTest.groovy#L542-L566 The production class uses double-checked locking for lazy and optional initialization of a field. Due to that, I wanted to replace the write lock and read lock by spies, that decorate the real ones and fail-fast if the write lock gets requested without first releasing the read lock to still kill the mutant but not having to wait for the timeout. I wanted to simply do this for all tests in a But I wanted to reach 100% branch coverage and to reach that with the double-checked locking, I needed to have another Spy around the write lock spy, added in the test, so that I can set the initialized field between the outer and inner I can of course do it like I do it now, but I think it is hackier than necessary if the spying on spies would work properly. I would really appreciate if this would be fixed. |
Spies (in 1.3) work by creating an instrumented version of the target objects class and then creating a new instance and copying all the state over, so you don't have the wrapping of objects you think you are getting. Mock/Spy interaction matching works by target identity, since you are basically creating two separate instances they don't have any relationship hierarchy. Adding a check, that the target of a spy is not a mock object would make sense. |
I see, sad, but yes, then at least an error should come up. :-) |
To kill some PIT mutants, I added a Spy that verifies some condition and then uses
callRealMethod()
in asetup()
method.In some tests I also added a
Spy
on the same object that also callscallRealMethod()
.so in the end it was like
Now if
testee.field.someMethod()
is called I would have expected that the second spy tests "some other condition", then delegates to the first spy which tests "some condition" and then delegates to the real method.Unfortunately, the first spy was skipped and after testing "some other condition" the second spy delegated to the real method directly.
This causes the mutant to not be killed properly (or rather a timeout due to a deadlock which costs more time than would have been necessary).
I worked around it by instead using a helper method that gets a closure, but it would be nice if it would actually work like expected. The workaround looks something like:
The text was updated successfully, but these errors were encountered: