I have a problem with raising an event on a mocked object. I am using Rhino Mocks 3.4. I have studied similar questions, but failed to reproduce any of the suggested solutions.
I have a class -- Foo -- which have a private method, that is only accessed by event invokation by an injected interface -- IBar.
How do I raise the event IBar.BarEvent, from a RhinoMock object, so I can Test the method in Foo?
Here is my code:
[TestFixture]
public sealed class TestEventRaisingFromRhinoMocks
{
[Test]
public void Test()
{
MockRepository mockRepository = new MockRepository();
IBar bar = mockRepository.Stub<IBar>();
mockRepository.ReplayAll();
Foo foo = new Foo(bar);
//What to do, if I want invoke bar.BarEvent with value =123??
Assert.That(foo.BarValue, Is.EqualTo(123));
}
}
public class Foo
{
private readonly IBar _bar;
private int _barValue;
public Foo(IBar bar)
{
_bar = bar;
_bar.BarEvent += BarHandling;
}
public int BarValue
{
get { return _barValue; }
}
private void BarHandling(object sender, BarEventArgs args)
{
//Eventhandling here: How do I get here with a Rhino Mock object?
_barValue = args.BarValue;
}
}
public interface IBar
{
event EventHandler<BarEventArgs> BarEvent;
}
public class BarEventArgs:EventArgs
{
public BarEventArgs(int barValue)
{
BarValue = barValue;
}
public int BarValue { get; set; }
}
Something like this I think:
bar.Raise(x => x.BarEvent += null, this, EventArgs.Empty);
http://ayende.com/wiki/Rhino+Mocks+3.5.ashx#Howtoraiseevents
You need an IEventRaiser, which you can get via
bar.BarEvent += null;
var eventRaiser = LastCall.IgnoreArguments().GetEventRaiser();
Then, when you want to raise the event, you can call eventRaiser.Raise with the required arguments, e.g. sender and event args (depends on your event handler definition).
(Edit: this is based on Rhino.Mocks 3.1!)
Related
I am doing some unit tests with NUnit and NSubstiture.
I have this class:
public class Presenter
{
public Presenter()
{
}
private readonly IView _view;
public Presenter(IView view)
{
_view = view;
this._view.Loaded += OnLoaded;
}
private void OnLoaded()
{
_view.Render("Hello Word");
}
}
And I have this Interface:
public interface IView
{
event Action Loaded;
void Render(string text);
}
And I have already a unit test with the NSubstiture framework, like this:
[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithMockingFramework()
{
var mockView = Substitute.For<IView>();
Presenter p = new Presenter(mockView);
mockView.Loaded += Raise.Event<Action>();
mockView.Received().Render(Arg.Is<string>(s => s.Contains("Hello World")));
}
But now I want for just testing purpose, write the same unit test , but then without the NSubstiture framework:
[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithoutMockingFramework()
{
IView view;
Presenter MockingVIew = new Presenter(view);
}
But how to do this?
Thank you
I try it like this:
public class FakePresenter : IView
{
public event Action Loaded;
public void Render(string text)
{
}
}
[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithoutMockingFramework()
{
//FakeMockingVIew = new Presenter(view);
FakePresenter fPresenter = new FakePresenter();
Presenter p = new Presenter(fPresenter);
fPresenter.Loaded += Raise.Event<Action>();
fPresenter.Received();
Assert.That(fPresenter, Is.EqualTo());
}
If you no longer want to use the mocking framework, nothing is stopping you from creating a class derived from IView yourself and using that as the dependency in the test
public class MyTestClass {
public class FakePresenter : IView {
public event Action Loaded = delegate { };
public void Render(string text) {
RenderedText = text;
}
public string RenderedText { get; private set; }
public void Load() {
Loaded();
}
}
[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithoutMockingFramework() {
//Arrange
var fake = new FakePresenter();
var subject = new Presenter(fake);
var expected = "Hello Word";
//Act
fake.Load();
var actual = fake.RenderedText;
//Assert
Assert.AreEqual(expected, actual);
}
}
The above implementation of the dependency exposes a Load() method to raise the event for all subscribers and also a RenderedText property to capture the text passed into the Render method so that an assertion can be made based on the value.
When you used NSubstitute, you had to tell the mock view to raise an event. But since the IView interface doesn't allow you to trigger the event, only add an event listener, NSubstitute does a workaroud, by attaching a special event handler, it actually triggers an event (I'm not familiar with NSubstitute, but I assume this is what happens):
// Code here says "attact an event handler", but NSubstitute recognizes this
// special event handler and raises the event to the "real" hanlders instead
mockView.Loaded += Raise.Event<Action>();
So when you move away from NSubstitute, you need to actually trigger the event the "correct" way from the fake view class:
public class FakeView : IView
{
private string RenderedText { get; private set; }
public event Action Loaded;
public void Render(string text)
{
renderedText = text;
}
public void RaiseLoaded() {
if (Loaded != null) Loaded();
}
}
Now you can easily trigger the events from your test:
[Test]
public void ctor_WhenViewIsLoaded_CallsViewRender_WithoutMockingFramework()
{
FakeView view = new FakeView();
Presenter p = new Presenter(fPresenter);
view.RaiseLoaded();
Assert.That(view.RenderedText, Is.EqualTo("Hello World"));
}
I started to transform my push -> pull bridge to a much simpler construct with Reactive Extensions.
So now I have a class with a (private) event, and an Observable created from it.
class WithEvents {
public class MyEvent {}
private delegate void MyEventHandler(MyEvent e);
private event MyEventHandler EventRaised;
Public IObservable<MyEvent> TheEvents;
public void Foo() {
EventRaised(new MyEvent());
}
}
Thing is, this event seems like unneeded scaffolding here. So I was wondering: is there a way to construct a 'bare' Observable, that I can just 'push' events to?
class WithChannel {
public class MyEvent {}
public IObservable<MyEvent> EventRaised {get} = new Channel<MyEvent>();
public void Foo() {
((Channel)EventRaised).DoNext(new MyEvent());
}
}
Yes, there is a thing called Subject (in System.Reactive.Subjects namespace) which does exactly that:
class WithChannel {
public class MyEvent {
}
private readonly Subject<MyEvent> _event;
public WithChannel() {
_event = new Subject<MyEvent>();
}
public IObservable<MyEvent> EventRaised => _event;
public void Foo() {
_event.OnNext(new MyEvent());
}
}
Usage of subjects is generally not recommended, but for this specific task I think it's fine.
with the code posted below I want to update progressbar from foo1.
but I'm unable to implement eventhandler in Foo
class Foo : Form // implements progressbar
{
IFoo foo = new Foo1()
// this will not do:
ProgressBarEventHandler = new EventUpdateProgressBar(this.UpdateProgressBar);
UpdateProgressBar() { }
}
public delegate void EventUpdateProgressBar();
class FooBase
{
public EventUpdateProgressBar ProgressBarEventHandler;
protected virtual void UpdateProgressBar()
{
if (ProgressBarEventHandler != null)
ProgressBarEventHandler();
}
}
class Foo1 : IFoo,FooBase { base.UpdateProgressBar() }
class Foo2 : IFoo,FooBase {}
interface IFoo {}
is there a way to get this working or is there a better approach ?
I'm not completely sure what your intent was, but if you're trying to implement two classes, one of which raises events while the other handles them, then the minimal sample would look as follows.
delegate void MyEvent();
class MyEventSource
{
public event MyEvent Event;
public void RaiseEvent()
{
MyEvent evt = Event;
if (evt != null)
evt();
}
}
class MyEventListener
{
public void SubscribeForEventFromMyEventSource(MyEventSource eventSource)
{
eventSource.Event += this.EventHandler;
}
public void EventHandler()
{
// Event handling logic here
}
}
More reading on events is available here: https://msdn.microsoft.com/en-us/library/9aackb16(v=vs.110).aspx and here https://codeblog.jonskeet.uk/2015/01/30/clean-event-handlers-invocation-with-c-6/
I want an abstract class that raises an event, this event will be raised by the concrete class.
What I want is when I use another class to listen to these events the signature of the delegate should have the concrete type not the abstract, I don't want to cast it.
For the moment I have come up with this solution. It works but I don't find it particularly clever especially because of the "STUPID, DOESN'T MAKE SENSE......" part.
Here is my solution :
public delegate void ClassAEventHandler<TClassA>(TClassA classA) where TClassA : ClassA;
//Abstract class that raise Event
public abstract class ClassA<TClassA> : where TClassA : ClassA
{
public event ClassAEventHandler<TClassA> onClassEventRaised;
private TClassA eventClassA;
public void registerEventClass(TClassA classA)
{
this.eventClassA = classA;
}
public void raiseClassEvent()
{
this.onClassEventRaised(this.eventClassA);
}
}
// Exemple of concrete type
public class ClassB : ClassA<ClassB> // <------ IT SEEMS DUMB
{
public void action()
{
//Do something then raise event
this.raiseClassEvent();
}
public void saySomething() {};
}
// Exemple of concrete type
public class ClassC : ClassA<ClassC> // <------ IT SEEMS DUMB
{
public void command()
{
//Do something then raise event
this.raiseClassEvent();
}
public void destroySomething() {};
}
//Class that listen to the event raised
public class MyEventListener
{
private ClassB classB;
private ClassC classC;
public MyEventListener()
{
this.classB = new ClassB();
this.classB.registerEventClass(this.classB); // <------ STUPID, DOESN'T MAKE SENSE......
this.classB.onClassEventRaised += classB_onClassEventRaised;
this.classC = new ClassC();
this.classC.registerEventClass(this.classC); // <------ STUPID, DOESN'T MAKE SENSE......
this.classC.onClassEventRaised += classC_onClassEventRaised;
}
public void classB_onClassEventRaised(ClassB classB)
{
classB.saySomething();
}
public void classC_onClassEventRaised(ClassC classC)
{
classC.destroySomething();
}
//What i don't want
/*
public void classB_onClassEventRaised(ClassA classA)
{
((classB)classA).saySomething();
}
*/
}
First of all, you're not following regular event design in .NET.
Instead of implementing your own delegate, use EventHandler<TArgs>, and create a derived class of EventArgs.
Your CustomEventArgs should have a T generic parameter:
public class CustomEventArgs<T> where T : A
{
private readonly T _instance;
public CustomEventArgs(T instance)
{
_instance = instance;
}
public T Instance { get { return _instance; } }
}
Also, don't implement a custom way of registering events. If you want to encapsulate how handlers are added to the event, you need to use event accessors.
Finally, you could implement your classes as follows:
public class A<T> where T : A
{
private event EventHandler<CustomEventArgs<T>> _someEvent;
// An event accessor acts like the event but it can't be used
// to raise the event itself. It's just an accessor like an special
// event-oriented property (get/set)
public event EventHandler<CustomEventArgs<T>> SomeEvent
{
add { _someEvent += value; }
remove { _someEvent -= value; }
}
protected virtual void RaiseSomeEvent(CustomEventArgs<T> args)
{
// If C# >= 6
_someEvent?.Invoke(this, args);
// Or in C# < 6
// if(_someEvent != null) _someEvent(this, args);
}
}
public class B : A<B>
{
public void DoStuff()
{
// It's just about raising the event accessing the whole
// protected method and give an instance of CustomEventArgs<B>
// passing current instance (i.e. this) to CustomEventArgs<T>
// constructor.
RaiseSomeEvent(new CustomEventArgs<B>(this));
}
}
Now, if you try to handle SomeEvent, you'll get the CustomEventArgs<B> typed as B instead of A:
B b = new B();
b.SomeEvent += (sender, args) =>
{
// args.Instance is B
B instance = args.Instance;
};
b.DoStuff(); // Raises SomeEvent internally
Consider the following constellation.
public delegate void BarHandler(Foo sender, FooEventArgs<Object> args);
public delegate void BarHandler<T>(Foo<T> sender, FooEventArgs<T> args);
public interface Foo
{
Object Value
{ get; }
event BarHandler BarEvent;
void Update();
}
public interface Foo<T> : Foo
{
new T Value
{ get; }
new event BarHandler<T> BarEvent;
}
public class Baz<T> : Foo<T>
{
Object Foo.Value
{ get { return Value; } }
public T Value
{ get; set; }
private BarHandler handler;
event BarHandler Foo.BarEvent
{
add{ handler += value; }
remove{ handler -= value; }
}
public event BarHandler<T> BarEvent;
public void Update()
{
BarEvent(this, new FooEventArgs<T>());
(this as Foo).BarEvent(this, new FooEventArgs<Object>());
}
}
I have a Interface and a Generic Interface which extends the first Interface and a class that extends the generic Interface. The generic interface hides the not generic one, via the new keyword.
The Update method should raise both, the not-generic and the generic one. And that is the problem I am dealing with at the moment.
The resulting error is:
The event BarEvent can only appear on the left hand side of += or -= when used outside of Foo.
But I am in Foo, or do I miss something?
So, what I want is, regardless on which event the client has been registerd, it should be notified. I also should mention, that both, add and remove must work, so there is no option with delegates or something like that.
Just use the private handler variable, this should do the trick.
public void Update()
{
BarEvent(this, new FooEventArgs<T>());
handler(this, new FooEventArgs<Object>());
}
It would probably also be a good idea to check BarEvent and handler for null.