Closed ian-twilightcoder closed 4 years ago
This is based on the suggestion in the issue by @fareal that -stopMocking
be used to release arguments to mock objects, and potentially break retain cycles that can result as described by @alexito4.
The gotcha here is that mocks can no longer be verified after -stopMocking
has been called. In practice I don't see how that could be an issue, but it is a behavior change that I want to point out up front.
I don't see any great alternatives though.
-stopMocking
would then restore the original problem where the invocations can hold zombies, which can cause crashes. If you don't use the mock after -stopMocking
(and it seems to me like you really shouldn't) then it's not a problem. But if you do keep using the mock, probably to verify, it seems better to me to fail the verifies rather than sporadically crash.-stopMocking
, but I don't know if anyone actually wants to do that so I don't know if it's really worth adding another method.So I think the behavior change is worth it on principle, and I think it will make more people happy than it makes angry?
I think this proposal is fine on the face of it. -stopMocking
IMO is essentially -tearDown
for the mock. But using it afterwards should fail aggressively with appropriate warnings / messages.
Would you consider amending your diff to add a fault, maybe NSException
, or if we want to be really aggressive a hard coded call to abort()
if -expect
is called on a mock after -stopMocking
?
Also if I read this right -stopMocking
is now a required call for all types of mocks, not just class or partials?
No, this proposal doesn't make -stopMocking
a required call for any mocks where it wasn't already. It just makes it so that -stopMocking
can be used to manually release the captured invocations on the mock, rather than relying on the mock's own object lifecycle. This is particularly important when the mock retains objects that the real object normally wouldn't, and the objects it's retaining in turn hold a strong reference to the mock. Prior to this proposal there was no way out of that situation, but with this proposal you can now manually call -stopMocking
to break the retain cycle. So I wouldn't say this adds a requirement, but rather it adds an option to fix a previously un-fixable situation.
I'm not opposed to installing a land mine after -stopMocking
is called, but I think that should be a separate diff/proposal.
Hi @erikdoe what do you think of this one? I still think it's the best compromise between all the proposed solutions, code snippets, and pull requests for the issue. But I'm also happy to make changes as you prefer.
@erikdoe Any updates on this one? It's kind annoying that the arguments were captured after stopMocking
is called 😢
It certainly took a very long time for me to merge this. Somehow, against the odds, I was still hoping to find a more elegant solution. I didn't.
After merging this PR I also added the "land mines" mentioned above. If tests try to use the verify after run functionality or the mock itself, an exception will be thrown. I thought this was super important because without it, the exception thrown when trying to verify after run after stopMocking
would have been very misleading.
Woohoo! Thank you for checking this one out, and also doing the follow up land mines too!
OCMockObject invocations need to retain their arguments, however that can introduce retain cycles that wouldn't otherwise be there. It also makes dealloc tests fail for objects that get sent as arguments to mocks. Break the chain in -stopMocking by emptying out the invocations.
https://github.com/erikdoe/ocmock/issues/307