Home All Groups Group Topic Archive Search About
Author
22 Oct 2008 10:31 AM
Berryl Hesh
I am experimenting with a class of widgets, and trying to decide on a
general strategy for testing them. Say my button widget has a property in
it's interface of:
public event EventHandler Click;

If I implement this as a Win Forms button, I know I can use the implemented
buttons PreformClick() method to test it, but how can I do this more
generically, just using the .Net event? For example, in the sample test code
below, I think I want to do something like
    widgetHello.Click.Invoke(this, EventArgs.Empty);
which doesn't even compile much less work.

Thanks for the help - BH


[Test]
public void ClickEvent_CanBeDelegated_ToAnArbitraryMethod() {
    // arrange
    Assert.That(HelloMessage, Is.EqualTo(null));
    var btnHello = new Button {Text = "Click Me"};
    var widgetHello = new WinButton(btnHello);
    widgetHello.Click += delegate { SayHello(); };
    // act
    btnHello.PerformClick();
    // assert
    Assert.That(HelloMessage, Is.EqualTo("Hello World"));
}

Author
22 Oct 2008 10:36 AM
Marc Gravell
There isn't a safe way of raising an arbitrary event. In this case,
one option might be to add an "internal" method that raises the event
- for example (extending the typical protected virtual OnFoo method):

  public event EventHandler Foo;
  protected internal virtual void OnFoo() {
    if(Foo!=null) Foo(this,EventArgs.Empty);
  }

then use the [InternalsVisibleTo] attribute to allow your test project
access to the internal method. Your test project can now call OnFoo()
to raise the event.

This only works if you own the type, of course.

Marc
Are all your drivers up to date? click for free checkup

Author
11 Dec 2008 1:05 AM
Berryl Hesh
I'd like to be able to test Foo != null, and I don't understand the logic of
"Click' can only appear on the left hand side of += or -. Iis there another
way to determiine if an event is null from another class?

Thanks for sharing! BH


public event EventHandler Click;
protected internal virtual void OnClick() {
    if(Click!=null) Foo(this,EventArgs.Empty);
}
Author
11 Dec 2008 1:12 AM
Peter Duniho
On Wed, 10 Dec 2008 17:05:45 -0800, Berryl Hesh <efing***@yahoo.com> wrote:

> I'd like to be able to test Foo != null, and I don't understand the 
> logic of
> "Click' can only appear on the left hand side of += or -.

That's exactly what an event is and does.  If you "don't understand the 
logic" of that, then you probably don't really understand events 
themselves (see the C# specification or MSDN's discussion on the topic).  
Alternatively, if that restriction doesn't work for your intended design, 
then you shouldn't be using an event in the first place.

> Iis there another
> way to determiine if an event is null from another class?

Not unless you have control over the class implementing the event, and 
explicitly expose that information via a property or method.

The whole point of the event is that it encapsulates specific behavior, 
hiding the implementation from code outside the class where the event is 
declared.

Frankly, there's a good chance that what you're trying to do is not a good 
way to design the code anyway.  But, if you really feel that you need 
this, you need to either add a member to the class that will leak the 
event implementation to code outside the class, or you need to not use an 
event.

Pete
Author
11 Dec 2008 1:26 AM
Berryl Hesh
I understand the encapsulation side, ie, invoking the event. It's the
testing of whether its subscribed to that I don't grok.

What I want to do here is be able to trigger an event, in a test, so I know
it is doing what it should, especially after refactoring something. I also
like to test that the event has been subscribed to in test code (less
useful). I know I can provide hooks to do these things from the owning
class, but then I have broken encapsulation to do so.

Can you recommend a test framework for this?


Show quoteHide quote
"Peter Duniho" <NpOeStPe***@nnowslpianmk.com> wrote in message
news:op.uly4bljx8jd0ej@petes-computer.local...
> On Wed, 10 Dec 2008 17:05:45 -0800, Berryl Hesh <efing***@yahoo.com>
> wrote:
>
>> I'd like to be able to test Foo != null, and I don't understand the
>> logic of
>> "Click' can only appear on the left hand side of += or -.
>
> That's exactly what an event is and does.  If you "don't understand the
> logic" of that, then you probably don't really understand events
> themselves (see the C# specification or MSDN's discussion on the topic).
> Alternatively, if that restriction doesn't work for your intended design,
> then you shouldn't be using an event in the first place.
>
>> Iis there another
>> way to determiine if an event is null from another class?
>
> Not unless you have control over the class implementing the event, and
> explicitly expose that information via a property or method.
>
> The whole point of the event is that it encapsulates specific behavior,
> hiding the implementation from code outside the class where the event is
> declared.
>
> Frankly, there's a good chance that what you're trying to do is not a good
> way to design the code anyway.  But, if you really feel that you need
> this, you need to either add a member to the class that will leak the
> event implementation to code outside the class, or you need to not use an
> event.
>
> Pete
Author
11 Dec 2008 4:05 AM
Peter Duniho
On Wed, 10 Dec 2008 17:26:36 -0800, Berryl Hesh <efing***@yahoo.com> wrote:

> I understand the encapsulation side, ie, invoking the event. It's the
> testing of whether its subscribed to that I don't grok.

By design, events do not allow you to test that from outside the class.

> What I want to do here is be able to trigger an event, in a test, so I 
> know
> it is doing what it should, especially after refactoring something. I 
> also
> like to test that the event has been subscribed to in test code (less
> useful). I know I can provide hooks to do these things from the owning
> class, but then I have broken encapsulation to do so.

I don't understand why you feel the need to write tests that break 
encapsulation.  In OOP, encapsulation is everything.  Surely you don't 
break encapsulation to test the rest of your code?  The test should be 
testing the _encapsulated_ behavior of the class, because that's what 
matters to the client of the class.  You can include, in your debug build, 
internal consistency checks in the class itself, but expecting a test 
harness to be able to do that kind of checking isn't correct.

For an event, what you really should be testing is whether, after 
subscribing to it, your handler is called when the appropriate 
circumstances occur.  Even if you could arbitrarily cause the event to be 
raised, you're not testing the part of the code that actually matters 
anyway.  You need to test that your handler gets executed for real, when 
the real-world situation that would raise the event happens.  For that, 
there's no need to break encapsulation.

Pete
Author
12 Dec 2008 12:46 AM
Berryl Hesh
The point is to find useful techniques for *maintaining* encapsulation
(including event driven behavior) while providing engineered tests for the
entire codebase (including event driven behavior).

Ayende / RhinoMocks provides support for this on interface events
http://ayende.com/Wiki/How+to+raise+events+using+AAA+and+RR+syntax.ashx, and
Osherove / TeamAgile has something here
(http://weblogs.asp.net/rosherove/archive/2005/06/13/EventsVerifier.aspx

Thanks
Author
12 Dec 2008 1:20 AM
Peter Duniho
On Thu, 11 Dec 2008 16:46:11 -0800, Berryl Hesh <efing***@yahoo.com> wrote:

> The point is to find useful techniques for *maintaining* encapsulation
> (including event driven behavior) while providing engineered tests for 
> the
> entire codebase (including event driven behavior).
>
> Ayende / RhinoMocks provides support for this on interface events
> http://ayende.com/Wiki/How+to+raise+events+using+AAA+and+RR+syntax.ashx
> and
> Osherove / TeamAgile has something here
> (http://weblogs.asp.net/rosherove/archive/2005/06/13/EventsVerifier.aspx

I'm afraid I don't understand how either of those examples relate to or 
elaborate on your question.

My understanding of your question is that you want to know how to test 
using an event found in a production class.  Neither of those examples do 
that.

The first bypasses the production implementation of the event (they seem 
to have some kind of class that can mock interface implementations).  The 
second uses an explicitly exposed implementation detail of the class 
implementing the event (i.e. it relies on a method in the class that is 
known specifically to raise the event).

You can, as in the first example, use reflection to inspect anything in 
the class you want.  The first example doesn't seem to do what you are 
asking for, but you can use similar techniques to inspect the state of the 
class being tested to verify whatever it is you want to verify, just as 
the tool being discussed there must do.

Alternatively you can, as in the second example, just rely on the class 
that implements the event to provide you with a method that is used to 
raise the event, and just call that method.  But, we've already explained 
that particular approach, so I don't see what that second example adds to 
the discussion.

Pete



Post Thread options