Verifying event handler code executed - c#

I have code very similar to this but cannot work out how I test whether an event handler occured.
public class MyClass : MyAbstractClass
{
IFileSystem FileSystem;
public MyClass(IFileSystem myFileSys)
{
FileSystem = myFileSys;
FileSystem.EventHit += new EventHandler(FileSystem_EventHit);
}
public void FileSystem_EventHit(object sender, EventArgs e)
{
//Testing base.OnOutput is not possible which I wont go into
base.OnOutput("EventHit");
}
}
Testing code is here:
[Test]
public void DoSomething_WhenCalled_EventFired()
{
var mock = new Moq.Mock<IFileSystem>();
MyClass plugin = new MyClass (mock.Object);
mock.Object.DoSomething();
mock.Raise(x => x.EventHit += null, new EventArgs());
//Verify/Assert that MyClass handled and did something in the event handler
}

The simplest way I can think of is to just add your own handler in the test method, which should suffice I would think?
[Test]
public void DoSomething_WhenCalled_EventFired()
{
var mock = new Moq.Mock<IFileSystem>();
bool isHit = false;
mock.EventHit += (s, e) =>
{
isHit = true;
};
MyClass plugin = new MyClass (mock.Object);
mock.Object.DoSomething();
mock.Raise(x => x.EventHit += null, new EventArgs());
Assert.IsTrue(isHit);
}

As verifying something in the event handler would mean trying to test legacy code the option I went with was to test that the event fired from within the concrete type and not a mock.
[Test]
public void DoSomething_WhenCalled_EventFired()
{
FileSystem fs = new FileSystem(mock.Object, timerMock.Object);
bool WasItHit = false;
fs.EventHit += delegate { WasItHit = true; };
fs.DoSomething(); //This should call the event
Assert.IsTrue(WasItHit);
}

You need to inject a mock of whatever gets called as a result of the event handler invocation and verify it. Your comment says you can't test base base.OnOutput, but it seems to me that is exactly what you need to do.

Basically testing of a fact that method was called is not a valid test case, you should test a logic/behaviour behind a method. Obviously with a given event handler there is nothing to test, this is why a task looks not trivial.
Try out formulate in few words what are you trying to test, which test case. For instance
MyClass switches a state into the State==Hit whilst
FileSystem.EventHit event.

To do that you probably need a flag in MyClass indicating that event occured. I know, this will be just for purpose of running a test but sometimes is good to have something like that.

Related

raise event Action in moq

I have structure as below. I want to test if LoadData is called when ViewLoaded event is triggered.
public interface ISetupView
{
event Action ViewLoaded;
}
public class BaseSetupController
{
private ISetupView view;
public BaseSetupController(ISetupView view)
{
this.view = view;
view.ViewLoaded += () => { LoadData(); };
}
public virtual void LoadData()
{
}
}
Currently I have test like below, but it is not working. It states that LoadData is never called.
[TestFixture]
public class BaseSetupControllerTests
{
[Test]
public void ViewLoad_LoadDataIsCalled()
{
Mock<ISetupView> view = new Mock<ISetupView>();
Mock<BaseSetupController> controller = new Mock<BaseSetupController>(view.Object);
controller.Setup(x => x.LoadData());
view.Raise(x => x.ViewLoaded += () => { });
controller.Verify(x=>x.LoadData(), Times.Once());
}
}
It seems that I just needed to create controller.Object before raising event:
var obj = controller.Object;
view.Raise(x=>x.ViewLoaded+=null);
Setting the event handler happens in the constructor, which isn't called if you're only mocking the object.
In a unit test, you have one concrete class. Its dependencies are what you'd mock.
Mocking them both basically only tests the mocking framework, not your class.
Since you want to test whether LoadData is called, you're probably interested if the event handler is set to LoadData. That LoadData is actually called when the event is raised is a given, unless you doubt the .NET framework itself.
This question discusses verifying whether an event has a specific subscriber. But it requires reflection and is not easy.

Trying to Unit Test an Event with JustMock

I am trying to write a Unit Test using JustMock that ignores an Event.
I do not want to test the Event itself, as it calls all sorts of internal functions that would require a massive amount of effort to Mock.
Here is a quick bit of example code:
public class Sample
{
public delegate void OneParameterFunction(int someVar);
public event OneParameterFunction TheEvent;
public Sample()
{
TheEvent += CallMe;
}
public void CallMe(int someVar)
{
Debug.WriteLine("CallMe was fired with parameter: " + someVar);
}
public void FireEvent()
{
// do stuff, business logic here...
if (TheEvent != null)
TheEvent(3);
}
}
And here is the test I would Love to write, but cannot:
[TestClass]
class EventMocking
{
[TestMethod]
public void DoNothingOnEvent()
{
var s = new Sample();
Mock.Arrange(() => s.TheEvent(Arg.AnyInt))
.DoNothing();
Mock.Arrange(() => s.CallMe(Arg.AnyInt))
.OccursNever();
s.FireEvent();
Mock.Assert(() => s.CallMe(Arg.AnyInt));
}
}
But I receive the following compiler error:
Error 1 The event 'Sample.TheEvent' can only appear on the left hand side of += or -= (except when used from within the type 'Sample') C:\BizObjectTests\EventMocking.cs
Does anyone have any suggestions about how to stop an Event from propagating? I also do not want to Mock.Create<T> for a number of reasons, one being I would again, have to setup a lot more test data/objects.
It's impossible to mock the delegate invocation itself, since it's implemented internally by the JIT.
You have several alternative options. If you raise the event in a method dedicated for that purpose (as in your sample), then you can simply mock that method instead. So, in your sample that becomes:
Mock.Arrange(() => s.FireEvent()).DoNothing();
If that's not possible then you can mock the method that adds handlers to the event (the one called when Sample += ... is invoked). You can do this like so:
var mock = Mock.Create<Sample>(); // we need this just for the following arrangement
Mock.ArrangeSet(() => mock.TheEvent += null).IgnoreInstance().IgnoreArguments().DoNothing();
var real = new Sample(); // TheEvent += CallMe will now do nothing
real.FireEvent(); // TheEvent is empty
Finally, as a third option, you can remove all handlers from the event using reflection at some point where you know the event is just about to be fired, or that no one else will attach to it:
new PrivateAccessor(real).SetField("TheEvent", null);
real.FireEvent(); // TheEvent is null right now
Caveat: this last option is dependent on the compiler implementation. It will work for event declarations in C# code, but will not work for VB events.

Mocking EventHandler

Having defined an interface
public interface IHandlerViewModel {
EventHandler ClearInputText { get; }
}
I would like to test if ClearInputText is invoked by some method.
To do so I do something like this
SomeType obj=new SomeType();
bool clearCalled = false;
var mockHandlerViewModel=new Mock<IHandlerViewModel>();
mockHandlerViewModel.Setup(x => x.ClearInputText).Returns(delegate { clearCalled = true; });
obj.Call(mockHandlerViewModel.Object);//void Call(IHandlerViewModel);
Assert.IsTrue(clearCalled);
which fails. Simply the delegate is not called.
Please help me with this.
The example you give isn't clear. You're essentially testing your own mock.
In a scenario where the mocked proxy is passed as a dependency to an object under test, you do no set up the event handler, you Raise it.
var mockHandlerViewModel = new Mock<IHandlerViewModel>();
var objectUnderTest = new ClassUnderTestThatTakesViewModel(mockHandlerViewModel.Object);
// Do other setup... objectUnderTest should have registered an eventhandler with the mock instance. Get to a point where the mock should raise it's event..
mockHandlerViewModel.Raise(x => x.ClearInputText += null, new EventArgs());
// Next, Assert objectUnderTest to verify it did what it needed to do when handling the event.
Mocks either substitute the event source by using .Raise(), or they substitute an object that will consume another class under test's event (to assert the event was raised), in which case you use .Callback() to record "handling" the event in a local flag variable.

How can I test that an event contains an event handler?

I want to test that class A's RegisterEventHandlers() method registers one of its methods as an EventHandler for an event on class B. How can I do that? I'm using moq, if that matters.
I don't think there's a way to inspect the event handler delegate from outside the class (please correct me if I'm wrong).
It'd be nice if I could trigger the event and then assert that my callback was called, but if I mock the interface of the A class (and set up an expectation for the callback) then I lose the implementation of RegisterEventHandlers(), which is the method I'm testing in the first place.
Mocking the B class's event would be the best option, but I don't see what method I'd have to intercept to do this. Is there some way to set up a mock for an event, and intercept the += method call?
Is there a clean solution to this?
You can get the invocation list for an event outside the class declaring the event - but it involves reflection. Below is a code example showing how you can determine which methods (on target instance a) are added to the event b.TheEvent after a call to a.RegisterEventHandlers(). Paste the code below in a code file and add to a form or console project: Test test = new Test(); test.Run();
using System;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
public class A
{
B m_b = new B();
public void RegisterEventHandlers()
{
m_b.TheEvent += new EventHandler(Handler_TheEvent);
m_b.TheEvent += new EventHandler(AnotherHandler_TheEvent);
}
public A()
{
m_b.TheEvent += new EventHandler(InitialHandler_TheEvent);
}
void InitialHandler_TheEvent(object sender, EventArgs e)
{ }
void Handler_TheEvent(object sender, EventArgs e)
{ }
void AnotherHandler_TheEvent(object sender, EventArgs e)
{ }
}
public class B
{
public event EventHandler TheEvent;
//{
// //Note that if we declared TheEvent without the add/remove methods, the
// //following would still generated internally and the underlying member
// //(here m_theEvent) can be accessed via Reflection. The automatically
// //generated version has a private field with the same name as the event
// //(i.e. "TheEvent")
// add { m_theEvent += value; }
// remove { m_theEvent -= value; }
//}
//EventHandler m_theEvent; //"TheEvent" if we don't implement add/remove
//The following shows how the event can be invoked using the underlying multicast delegate.
//We use this knowledge when invoking via reflection (of course, normally we just write
//if (TheEvent != null) TheEvent(this, EventArgs.Empty)
public void ExampleInvokeTheEvent()
{
Delegate[] dels = TheEvent.GetInvocationList();
foreach (Delegate del in dels)
{
MethodInfo method = del.Method;
//This does the same as ThisEvent(this, EventArgs.Empty) for a single registered target
method.Invoke(this, new object[] { EventArgs.Empty });
}
}
}
public class Test
{
List<Delegate> FindRegisteredDelegates(A instanceRegisteringEvents, B instanceWithEventHandler, string sEventName)
{
A a = instanceRegisteringEvents;
B b = instanceWithEventHandler;
//Lets assume that we know that we are looking for a private instance field with name sEventName ("TheEvent"),
//i.e the event handler does not implement add/remove.
//(otherwise we would need more reflection to determine what we are looking for)
BindingFlags filter = BindingFlags.Instance | BindingFlags.NonPublic;
//Lets assume that TheEvent does not implement the add and remove methods, in which case
//the name of the relevant field is just the same as the event itself
string sName = sEventName; //("TheEvent")
FieldInfo fieldTheEvent = b.GetType().GetField(sName, filter);
//The field that we get has type EventHandler and can be invoked as in ExampleInvokeTheEvent
EventHandler eh = (EventHandler)fieldTheEvent.GetValue(b);
//If the event handler is null then nobody has registered with it yet (just return an empty list)
if (eh == null) return new List<Delegate>();
List<Delegate> dels = new List<Delegate>(eh.GetInvocationList());
//Only return those elements in the invokation list whose target is a.
return dels.FindAll(delegate(Delegate del) { return Object.ReferenceEquals(del.Target, a); });
}
public void Run()
{
A a = new A();
//We would need to check the set of delegates returned before we call this
//Lets assume we know how to find the all instances of B that A has registered with
//For know, lets assume there is just one in the field m_b of A.
FieldInfo fieldB = a.GetType().GetField("m_b", BindingFlags.Instance | BindingFlags.NonPublic);
B b = (B)fieldB.GetValue(a);
//Now we can find out how many times a.RegisterEventHandlers is registered with b
List<Delegate> delsBefore = FindRegisteredDelegates(a, b, "TheEvent");
a.RegisterEventHandlers();
List<Delegate> delsAfter = FindRegisteredDelegates(a, b, "TheEvent");
List<Delegate> delsAdded = new List<Delegate>();
foreach (Delegate delAfter in delsAfter)
{
bool inBefore = false;
foreach (Delegate delBefore in delsBefore)
{
if ((delBefore.Method == delAfter.Method)
&& (Object.ReferenceEquals(delBefore.Target, delAfter.Target)))
{
//NOTE: The check for Object.ReferenceEquals(delBefore.Target, delAfter.Target) above is not necessary
// here since we defined FindRegisteredDelegates to only return those for which .Taget == a)
inBefore = true;
break;
}
}
if (!inBefore) delsAdded.Add(delAfter);
}
Debug.WriteLine("Handlers added to b.TheEvent in a.RegisterEventHandlers:");
foreach (Delegate del in delsAdded)
{
Debug.WriteLine(del.Method.Name);
}
}
}
When mocking B, declare the EventHandler like this:
public class B : IB
{
public int EventsRegistered;
public event EventHandler Junk
{
add
{
this.EventsRegistered++;
}
remove
{
this.EventsRegistered--;
}
}
}
I'm not certain that moq allows this, but I'm sure you can create your own mock class.
You are correct that you cannot access the event delegates from outside the class, this is a limitation within the C# language.
The most straight-forward approach to test this, would be to mock class B and then raise it's event and then observe the side-effects of the event being raised. This is slightly different than what you're looking for but it demonstrates class's A behavior rather than its implementation (this is what your tests should strive to do).
In order for this to work, class B must be mockable and the event that it exposes must also be virtual. Moq can't intercept events if they're not declared as virtual. Alternatively, if B is an interface be sure that the event is declared there.
public interface IEventProvider
{
event EventHandler OnEvent;
}
public class Example
{
public Example(IEventProvider e)
{
e.OnEvent += PerformWork;
}
private void PerformWork(object sender, EventArgs e)
{
// perform work
// event has an impact on this class that can be observed
// from the outside. this is just an example...
VisibleSideEffect = true;
}
public bool VisibleSideEffect
{
get; set;
}
}
[TestClass]
public class ExampleFixture
{
[TestMethod]
public void DemonstrateThatTheClassRespondsToEvents()
{
var eventProvider = new Mock<IEventProvider>().Object;
var subject = new Example(eventProvider.Object);
Mock.Get(eventProvider)
.Raise( e => e.OnEvent += null, EventArgs.Empty);
Assert.IsTrue( subject.VisibleSideEffect,
"the visible side effect of the event was not raised.");
}
}
If you really need to test the implementation, there are other mechanisms available, such as a hand-rolled Test Spy / Test Double, or reflection-based strategy to get the delegate list. My hope is that you should be more concerned with class A's event handling logic than its event handler assignment. After all, if class A doesn't respond to the event and do something with it, the assignment shouldn't matter.
I don't know much about unit testing, but perhaps this link can give you some ideas. Note that the virtual keyword also works there.
I don't think moq has that capability - if you're prepared to purchase a tool I suggest you use Typemock Isolator that can verify that any method on an object was called - including event handler - have a look at link.

How to test a delegated method

I have a simple method in a class that is responsible to register a FileSystemWatcher given a certain path in appconfig.xml:
public void ListenPath(string path){
//path validation code
//...
FileSystemWatcher objFileWatcher = new FileSystemWatcher();
objFileWatcher.Path = path;
objFileWatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
objFileWatcher.Filter = "*.txt";
objFileWatcher.Created += new FileSystemEventHandler(ProcessInput);
objFileWatcher.EnableRaisingEvents = true;
}
In my unit test I have to assert:
1) Giving a wrong or null path it should raise an PathNotFoundException
2) That ProcessInput method was correctly registered to listen to "path" when files are created.
How can I perform the unit test for item 2?
thanks a lot
Registering a callback on an event is simply populating a variable. It's more or less adding a callback to a list of callbacks. I don't generally validate incidental stuff like population of a list, unless data population is the whole point of the class (like if the class represented a custom data structure).
You can instead validate that ProcessInput gets called when you modify the specified file. A couple ways to go about this:
Test side-effects of ProcessInput, e.g. it populated some other structure or property in your program
Separate out the ProcessInput method into another class or interface. Take a reference to this type as an argument to ListPath, or the constructor for the class. Then mock that type
Mock object example:
public interface IInputProcessor
{
void ProcessInput(Object sender, FileSystemEventArgs e);
}
public class ClassUnderTest
{
public ClassUnderTest(IInputProcessor inputProcessor)
{
this.inputProcessor = inputProcessor;
}
public void ListenPath(string path){
// Your existing code ...
objFileWatcher.Created +=
new FileSystemEventHandler(inputProcessor.ProcessInput);
// ...
}
private IInputProcessor inputProcessor;
}
public class MockInputParser : IInputProcessor
{
public MockInputParser()
{
this.Calls = new List<ProcessInputCall>();
}
public void ProcessInput(Object sender, FileSystemEventArgs args)
{
Calls.Add(new ProcessInputCall() { Sender = sender, Args = args });
}
public List<ProcessInputCall> Calls { get; set; }
}
public class ProcessInputCall
{
public Object Sender;
public FileSystemEventArgs Args;
}
[Test]
public void Test()
{
const string somePath = "SomePath.txt";
var mockInputParser = new MockInputParser();
var classUnderTest = new ClassUnderTest(mockInputParser);
classUnderTest.ListenPath(somePath);
// Todo: Write to file at "somePath"
Assert.AreEqual(1, mockInputParser.Calls.Count);
// Todo: Assert other args
}
If the FileSystemWatcher is something you have access to, you can set it up so that you can mock the firing of the Created event. But I suspect it's not, which means you're getting to the point here where true "unit testing" isn't very easy.
You could try using an isolator like TypeMock or maybe Moles to simulate the firing of the Created event. But the easiest thing might be to actually write a test that creates a file at the given path, and ensure that the ProcessInput method gets called when that happens.
Because you haven't shown the definition or any other code around ProcessInput itself, I don't know the best way to go about ensuring that it got called.
You could split your method into two: the first method simply instantiates, configures and returns an instance of the FileSystemWatcher. You could then easily test on the returned result object. A second method could take it as argument and simply enable rising events on it.

Categories