I am using RhinoMocks, and I have a Mock which has a property I need to behave as a real property - updating its value when set, and also trigger PropertyChanged when the property is changed.
The interface of the mocked object is in essence this:
public interface IFoo
{
event PropertyChangedEventHandler PropertyChanged;
int Bar { get; set; }
}
When creating the mock I set PropertyBehavior - which makes it actually update its faked value:
var mocks = new MockRepository();
var fakeFoo = mocks.DynamicMock<IFoo>();
SetupResult.For(fakeFoo.Bar).PropertyBehavior();
But when I update the value PropertyChanged isn't triggered. Now, the interface doesn't implement the INotifyPropertyChanged interface as it is an interface.. How can I make PropertyChanged triggered?
The role of listener and mutator may sometimes be combined in the same class (e.g. in an adapter), but both roles should not be tested together.
In one test, you merely verify that your listening class reacts to the PropertyChanged event as designed. You don't care about what caused the property to change in that test:
[Test]
public void Updates_Caption_when_Bar_PropertyChanged()
{
var foo = MockRepository.GenerateStub<IFoo>();
foo.Bar = "sometestvalue1";
var underTest = new UnderTest(foo);
// change property and raise PropertyChanged event on mock object
foo.Bar = "sometestvalue2";
foo.Raise(x=>x.PropertyChanged+=null,
foo,
new PropertyChangedEventArgs("Bar"));
// assert that the class under test reacted as designed
Assert.AreEqual("sometestvalue2", underTest.Caption);
// or if the the expected state change is hard to verify,
// you might just verify that the property was at least read
foo.AssertWasCalled(x => { var y = foo.Bar; } );
}
In another test, you verify that your class plays its mutator role as designed:
[Test]
public void Reset_clears_Foo_Bar()
{
var foo = MockRepository.GenerateStub<IFoo>();
foo.Bar = "some string which is not null";
var underTest = new UnderTest(foo);
underTest.Reset();
// assert that the class under test updated the Bar property as designed
Assert.IsNull(foo.Bar);
}
This way, it is never necessary to put real logic into your mock objects like you are trying to do. This does require that you design your classes for testability; it is hard to add such tests to existing classes. Hence the practice of test driven development.
I'm not an expert in RhinoMocks, but I wouldn't try to do that with any of the mock-framework I know (TypeMock I know the most).
I would implement something like:
public class FooFake: IFoo
{
public event PropertyChangedEventHandler PropertyChanged;
int _bar;
public int Bar
{
set
{
if( PropertyChanged != null )
PropertyChanged();
_bar = value;
}
get
{
return _bar;
}
}
}
Sorry. Nothing really clever. But I like this kind of stub as they can be resused.
Related
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.
I'm just starting out using AutoFixture and I'm enjoying the features just now. But I've just created an AutoMoqDataAttribute as Mark Seemann describes here.
But now I'm trying to mock an object that contains an ObservableCollection of items and in my Sut I am subscribing to the CollectionChanged event and handling when new items are added.
My Sut looks like:
public class Foo
{
public Foo(IBar barWithObservableCollection)
{
barWithObservableCollection.Items.CollectionChanged += this.OnItemsChanged;
}
public ObservableCollection<IFooThing> FooThings
{
get;
private set;
}
private void OnItemsChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
{
// Handle the new object and build a new IFooThing with it.
...
this.FooThings.Add(fooThing);
}
}
My IBar interface is simple and basically only contains the ObservableCollection:
public interface IBar
{
ObservableCollection<IBarThings> Items
{
get;
}
}
So in my original implementation of the test to make sure that new items were handled was with full mocking of the objects using Moq and tying everything together myself (I'll leave this out as it's unnecessary for my question). But as said I've attempted to move this to using AutoFixture and now my tests looks like:
[Theory, AutoMoqData]
public void TestNewIBarThingsAreCorrectlyHandled([Frozen]IBar bar, [Frozen]IBarThing barThing, Foo sut)
{
bar.Items.Add(barThing);
Assert.Equal(1, sut.FooThings.Count);
}
So I was expecting that the IBar.Items was auto setting up an ObservableCollection which it is and this was being subscribed to, which it also is. But when I do the call to bar.Items.Add the collection changed handler is not not called, although I can see that the Items count is incremented on the IBar object.
Is there something that I'm doing wrong? Have I got the wrong end of the stick and I will have to manually setup the collection as before, I'd rather not have to do this as I'm enjoying the cleaner syntax?
EDIT:
After the comment below I checked that the IBar object provided to the tests and to the Sut were the same, but it turns out that these are not the same object. I was under the impression that the [Frozen] attribute specified that each time that object was requested the same object reference would be returned?
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.
I am writing the unit test and receive exception when trying to raise the event from abstract class mock. Here is the sample code:
public abstract class AbstractBase : EntityObject
{}
[TestMethod]
public void MyTest()
{
var mock = new Mock<AbstractBase>();
var notificationMock = entityMock.As<INotifyPropertyChanged>();
var propertyChangedMapper = new PropertyChangedMapper();
bool eventReceived = false;
propertyChangedMapper.MyPropertyChanged +=
(sender, eventArgs) =>
{
eventReceived = true;
};
propertyChangedMapper.Subscribe((AbstractBase)notificationMock.Object);
Assert.IsFalse(eventReceived);
notificationMock.Raise(e=>e.PropertyChanged += null,
new PropertyChangedEventArgs("Property1"));
Assert.IsTrue(eventReceived);
}
Obviously I could use mock on INotifyPropertyChanged and event is risen just fine, but inside of PropertyChangedMapper I need to cast the sender to AbstractBase which fails if using Mock<INotifyPropertyChanged>
EDIT:
As per suggestion using Mock.As<>() seems to be the right way to go, the only problem above is that the event risen from notificationMock has nothing to do with the original mock of the object. Code:
notificationMock.Object.PropertyChanged += (s, e) =>
{
var result = "this one is fired as it should";
};
mock.Object.PropertyChanged += (s, e) =>
{
var result = "this one is not called but is actually what I need";
};
notificationMock.Raise(e => e.PropertyChanged += null,
new PropertyChangedEventArgs("Property1"));
You may be able to do the desired cast if you make your mock a mult-mock. Since Moq mocks are tied to an individual type via the generic argument, you must explicitly progressively add additional interfaces or super-classes to the mock, and then use the end product in your test. A quick example of how to do this is below.
var baseMock = new Mock<AbstractBase>();
var inpcMock = baseMock.As<INotifyPropertyChanged>();
// ...setup event...
propertyChangedMapper.Subscribe(inpcMock.Object);
// ... assertions ...
Given the way you're doing this, there is no implementation of the event. The interface itself is just the contract that says "I have a PropertyChanged event." If you want to raise that event, you have to provide a handler, even if it doesn't do anything. Implement the PropertyChanged event in your mocked class to raise the event.
UPDATE:
Try this code for your AbstractBase:
public abstract class AbstractBase : INotifyPropertyChanged
{
public virtual event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
Is your PropertyChanged event declared as a virtual event?
public abstract class AbstractBase : INotifyPropertyChanged
{
public virtual event PropertyChangedEventHandler PropertyChanged;
}
(See also: Jon Skeet on virtual events.)
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.