1

We have using Moq for two month now. However there is a problem which can not solve somehow.

In visual studio all tests succeeded just fine. On the build server there are several tests which failed. What they have in common is, that they use the "raise" method to throw an event. Our build server tests obfuscated what is good to find obfuscation errors. Every "normal" expectation like "Setup(something).Returns(something)" works. Only the raise event fails. the stacktrace looks like the following:

MESSAGE:
Test method Ade.Graphic.Presenter.Test.RoutingEngineTest.TestRouteOverLadderLinesWithFbd threw exception: 
System.ArgumentException: Could not locate event for attach or detach method Void ᜀ(ᦜ[ᢈ]).
+++++++++++++++++++
STACK TRACE:
    bei Moq.Extensions.GetEvent[TMock](Action`1 eventExpression, TMock mock)
   bei Moq.Mock`1.Raise(Action`1 eventExpression, EventArgs args)
   bei Ade.Graphic.Presenter.Test.RoutingEngineTest.TestRouteOverLadderLinesWithFbd()

The code for this is:

documentEventHandler.Raise(stub => stub.DocumentChanged += null,
                                                new DocumentChangeEventArgs(DocumentChangeTypes.ViewUpdate));

We have no idea what is the difference between the code above and this

eventHandler.SetupGet(stub => stub.DocumentChangeNotify).Returns(documentEventHandler.Object);

because this code works fine.

Does anyone had the same problem or at least can tell what the difference is?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Yggdrasil
  • 1,377
  • 2
  • 13
  • 27
  • Moq just uses a reflection call like myType.GetEvent(name). Looks like the event name has gone after obfuscation. Maybe it's a private or internal event. You must configure your obfuscation tool not to touch events like that. – Simon Mourier May 27 '13 at 08:54
  • But doesnt use mock also reflection for normal methods/properties like stub.DocumentChangeNotify in the example above? – Yggdrasil May 27 '13 at 10:32
  • Maybe these are public/protected, so it's not a problem (obfuscation tools usually only change internal/private members and types). – Simon Mourier May 27 '13 at 10:43
  • No they are also internal and obfuscated. -> I have checked it with ILSpy. – Yggdrasil May 27 '13 at 11:23
  • Moq doesn't probably use it the same way then. – Simon Mourier May 27 '13 at 11:55
  • This is what I want to know for sure. It is no good to exclude events from obfuscation just because the test does not run with obfuscated events. We want to find a better workaround if necessary. – Yggdrasil May 27 '13 at 12:18

1 Answers1

2

The error comes probably (not sure as not tested) from the fact that events (i.e. DocumentChanged) are actually generated as 2 accessors: add_DocumentChanged and remove_DocumentChanged . This is similar to the properties that have the get and set accessors.

What the obfuscator did most probably is rename this add_DocumentChanged and remove_DocumentChanged. However, looking at the moq source code, I can see that moq relies on the events accessor keeping the same name:

 var ev = addRemove.DeclaringType.GetEvent(
                            addRemove.Name.Replace("add_", string.Empty).Replace("remove_", string.Empty));

ev == null in this case, which raises an error.

In your second examples, you're using delegates which are not broken down into add_ and remove_ accessors.

You're probably better off not obfuscating events.

rivarolle
  • 1,528
  • 11
  • 18
  • Thx for the explanation. I will try it and report the result. – Yggdrasil May 29 '13 at 05:10
  • Seem to work. I excluded only the events from obfuscation and moq can find them. I am just curious what moq does with properties. There you have also to accessors get_... set_... Do you know this? – Yggdrasil May 29 '13 at 06:44