Here's a test I've already got (which compiles happily but doesn't yet pass as I don't have it all working) to test verifiable Setups on mocked delegates:
[Fact]
public void RoystonTest()
{
var mockRaiser = new Mock<INotifyPropertyChanged>();
var mockListener = new Mock<PropertyChangedEventHandler>(MockBehavior.Strict);
mockRaiser.Object.PropertyChanged += mockListener.Object;
mockListener
.Setup(x => x(mockRaiser.Object, It.Is<PropertyChangedEventArgs>(pcea => pcea.PropertyName == "blob")))
.Verifiable();
mockRaiser.Raise(x => x.PropertyChanged += null, new PropertyChangedEventArgs("blob"));
mockListener.Verify();
}
i.e. instead of your lambda looking like
mock.Setup(x => x.SomeCall(parameter1, ...))
you get
mock.Setup(x => x(parameter1, ...))
(and then internally that call on the delegate makes the real call to the mocked/proxied interface.)
Make sense?
My team and I basically do this manually quite a lot: if we have a FooListener delegate for an event somewhere, we end up cranking out an IFooListener interface with a method on it that matches the delegate signature, create a Mock<IFooListener> using Moq, subscribe that mock to the event, and then we can make assertions about what happened to that interface when the class under test is manipulated. (To find out whether the event was raised, and make assertions about its EventArgs, basically.) Works well, but it's messy having to write the interface by hand every time. I'm resisting calls to move (back) to Rhino Mocks - which does support exactly this sort of delegate mocking - as I much prefer the natural AAA syntax of Moq.
Cheers,
Royston.
On 02/03/2010 22:18, Daniel Cazzulino wrote:Not sure about this.How are you going to Setup/Verify if the thing is a Func? (say). How will the lambda look like?
On Tue, Mar 2, 2010 at 17:45, Royston Shufflebotham <roy...@shufflebotham.org> wrote:
Hi there,
I've finally gotten some time to have a look into this (arranging for Moq to support mocking of delegates). It seems that a simple way to achieve it is to:
At that point, calls against the 'mocked' delegate get turned into calls against the mocked interface, and in theory all of the normal recording/setup/verify stuff should work. (I've essentially been doing this for months by hand with Moq, and it's getting boring!)
- create an interface dynamically with a method declared on it whose signature matches that of the requested delegate
- create a proxy instance for the interface (with all the usual Moq recording support)
- create a real delegate of type D pointing at the method on the mocked interface instance
- return that
I've managed to get some way into this, and have Moq creating the dynamic interface, proxying it and returning the delegate instances; the problem area is that the object that calls are recorded against (the interface) are not the same object that was returned (the delegate) which looks like it goes against some Moq code assumptions and means a little more refactoring than I'd hoped.
Would you be happy to receive barely-compiling patches (against Moq Subversion) trunk and help out where I don't quite understand some of the implications?
Cheers,
Royston.
On 14/07/2009 23:31, Daniel Cazzulino wrote:Looking forward to it!
All help is appreciated :)
/kzu
--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471
On Tue, Jul 14, 2009 at 2:51 PM, Royston <roy...@shufflebotham.org> wrote:
That's a shame. It's a useful piece of functionality I was used to
having in Rhino Mocks...
<http://ayende.com/Wiki/Default.aspx?Page=Rhino+Mocks+Mocking
+Delegates>
Just to clarify why it's actually useful:
In the same way that we want to be able to check (using Moq) that a
class-under-test calls a particular method, it's very useful to be
able to test that your class raises an event (i.e. calls some
EventHandler or calls some other delegate). For instance, I currently
have an implementation of INotifyPropertyChanged and want to check
that events are raised correctly when setters are called. (I'm
interested in testing it as it's not completely trivial as some of the
properties are - unfortunately - interdependent.) But it would be
good to make the sort of assertions about the delegate calls that we
can about other methods, e.g. how many times, with what parameters,
etc.
If it's a reasonably simple thing to do for Moq, I'd be happy to knock
it together; I've certainly contributed to the Rhino Mocks source in
the past and that was pretty easy...
Cheers,
Royston.
Hi there,
It's been almost three months since I submitted this fix, which does include full unit tests. Any chance we can get it into the main source soon, preferably before the v4 release? (It's not in the v4 beta 3 code.)
Cheers,
Royston.
On 05/03/2010 23:11, Daniel Cazzulino wrote:Thanks a bunch!
Your contribution will almost surely end up in v4 :)
On Fri, Mar 5, 2010 at 18:12, Royston Shufflebotham <roy...@shufflebotham.org> wrote:
All done. Bizarrely the thing that took significant time was as I was preparing the patch and realised you were using tabs in the source, not spaces, and had to reformat my changes. That took more time to fix than did the dynamic interface fixups and reuse of a ModuleScope!
I've attached the patch to the issue raised, at http://code.google.com/p/moq/issues/detail?id=235.
I've focused on keeping the changes minimal, so whilst I introduced a CallInfo class to wrap up the bits of data in common between an InvocationExpression and a MethodCallExpression, I assigned that to a variable called methodCall so that the rest of the code didn't change.
As I mentioned in the issue, the public Moq API is totally unchanged. It just now allows delegate mocking whereas it didn't before.
Let me know what you think - I'd love to see this make it into a release in the near future?
Regards,
Royston.
P.S. In case I haven't already said - thanks for Moq, and for making the A-A-A pattern so easy to specify. I used to use Rhino Mocks (a lot) but find it a lot easier to get others up to speed on the Moq AAA syntax.
On 04/03/2010 00:06, Daniel Cazzulino wrote:Awesome progress!
keep me posted :)
On Wed, Mar 3, 2010 at 19:42, Royston Shufflebotham <roy...@shufflebotham.org> wrote:
Fine. I raised it as issue 235.
Regarding implementation, I've actually got it essentially all working now: all of the tests I put up on that issue now pass with the changes I've made, and, as far as I can see, the only problem I have right now is that the tests don't pass when all run together in one go because there's a problem with the automatic generation of the dynamic interface: I just need to investigate the way DynamicProxy spits out types a little more, and maybe ModuleScopes. Should be fairly quick...
I've managed to keep the changes fairly localised (Extensions.cs, Mock.cs, Mock.Generic.cs, tiny changes to de-genericise IProxyFactory/CastleProxyFactory) and I've kept the changes minimal. The main change is that instead of assuming we have a MethodCallExpression in Setup/Verify, it might be an InvocationExpression, and so we retrieve the method, arguments and target object in a slightly different way.
I'll do some tidyups, get the above problem sorted out (hopefully) and chuck some diffs at you soon with any luck.
Cheers,
Royston.
On 03/03/2010 14:57, Daniel Cazzulino wrote:nah, I could use help :)
so feel free to send the impl too, he
On Wed, Mar 3, 2010 at 10:19, Royston Shufflebotham <roy...@shufflebotham.org> wrote:
Sure. I'll get them together. They should compile with existing Moq (there's no external API change needed) but they explode when run.
I've also got a partial implementation together. Shall I carry on with that, or are you going to zip off and do the implementation in half the time? :)
Cheers,
Royston.