Wow!! Two entries in a day. And none of them is a rant. Is my blog hacked or something?
In my previous post I left an open-question and being an open-questions hater myself I proceeded to try to answer.
I need to put some context on the matter, otherwise it will be very hard to understand.
I have a class in the shape of a command. This class uses a collaborator class, invoking a method on that collaborator class with a different value a number of times.
I wanted to test that my collaborator was called with right number of times with the right arguments. It's not shown in the sample code for the sake of brevity, but I do have control over the number of times and can figure out the arguments that the collaborator will be passed. The test for this looks like:
For some reason ,this test kept failing and failing no matter the behavior of the mock or the inclusion of the MockFactory. It kept going to the real implementation of the object, even if I made sure that the right expectations were being recorded. Debugging told me that I could only query the last argument recorded and what I was getting was the first returned value!
I then used the 2.0 version of Moq and although I had a somehow different: I was able to query just the last argument recorded, but I got the right return value at least. Still not passing.
I migrated this only test to use RhinoMocks and worked flawlessly. Here is the code:
Wow, that was weird!! I couldn't believe Moq couldn't handle such a common situation. So I sharpened my eye and I realized that Resharper was uneasy with something in the moq test case. It was showing a warning labelled "access to modified closure". I googled it and entered a world in which really smart people excel and where I feel like a schoolboy of primary peeping thorough high school assignments.
Surprise, surprise, when the suggested refactoring was applied it all worked as expected.
And the refactoring is as simple as creating a local variable scoped within the foreach construct and copy the current value to it:
First take-away: obey Resharper.
But not blindly. You better know why they suggest the refactoring as some of them are not trivial at all and some other might not apply to your particular case. And that is just one of the things that make R# such an invaluable tool.
Second take-away: we are touching the edges of functional programming with .Net languages new additions. That is a complicated field and requires time to master. It offers unique and new ways to solve problems and requires lots of learning. Tools like Moq take you closer to that world, so get ready for dodging the problems that live there.
For the record, the problem is that, apparently, lambda expression and anonymous methods and delegates "do not represent a true lexical closure" whatever that means.
If you follow the links in the google result I pointed out before you might spend some enjoyable time remembering (or learning anew) concepts of functional programming and compilers. I, for myself, have not yet digested all that info, but that is going to be the task for the Sunday siesta that will surely come later.