Feature request: Assert.Raises, better Assert.Throws

71 views
Skip to first unread message

markheath

unread,
Sep 23, 2009, 5:33:23 AM9/23/09
to NUnit-Discuss
Hi,

First of all, great job on NUnit 2.5. I am really liking the new
features. I have a couple of feature requests for NUnit. (or perhaps
it can already do these, and I don't know about it).

My first request is that the Assert.Throws method takes another
delegate allowing you to verify the exception's properties. Something
like this:

Assert.Throws<InvalidOperationException>(() =>
objectUnderTest.DoSomething(),
e => Assert.AreEqual("My Test Message", e.Message);

The second problem is testing that your object raises a particular
event. Currently this usually involves writing an event handler that
saves the parameters to a local variable. But this can be error prone,
particularly if you forget to set that variable to null ready for the
next test.

I'm not sure quite how the syntax would work. First parameter should
(somehow) indicate which event you want to be raised, second would be
an action to execute, and a third optional parameter would let you
assert that the event's properties were as expected. Maybe something
like this:

Assert.Raises<MyEventArgs>(objectUnderTest.MyEvent,
() => objectUnderTest.DoSomething(),
(args) => Assert.AreEqual("Foo",args.Foo));

There may also be a need to support a version where the same event is
expected to be raised several times.

Assert.RaisesMany<MyEventArgs>(objectUnderTest.MyEvent,
() => objectUnderTest.DoSomething(),
(events) => Assert.AreEqual(5,events.Count));

What do you think? Is something like this possible? I think it would
be a good addition to the framework.

Mark

Kenneth Xu

unread,
Sep 23, 2009, 8:57:34 AM9/23/09
to nunit-...@googlegroups.com
For exception property you can use:

InvalidOperationException e = ( Assert.Throws<InvalidOperationException>(() =>
objectUnderTest.DoSomething());
Assert.AreEqual("My Test Message", e.Message);

At this moment
Sent from my Verizon Wireless BlackBerry

-----Original Message-----
From: markheath <mark....@gmail.com>

Date: Wed, 23 Sep 2009 02:33:23
To: NUnit-Discuss<nunit-...@googlegroups.com>
Subject: [nunit-discuss] Feature request: Assert.Raises, better Assert.Throws

markheath

unread,
Sep 23, 2009, 9:00:55 AM9/23/09
to NUnit-Discuss
thanks Kenneth, I realised that the minute after I posted. doh!

the same pattern could apply to my proposed Raises method - it could
return the arguments / list of arguments from events that were raised

Mark

markheath

unread,
Sep 23, 2009, 10:46:46 AM9/23/09
to NUnit-Discuss
I've blogged my best effort at creating an Assert.Raises method here:
http://mark-dot-net.blogspot.com/2009/09/asserting-events-with-nunit.html

It's not perfect, but it does a job for me now. It would be nice to
see this sort of thing added into a future NUnit version

Mark

Kenneth Xu

unread,
Sep 23, 2009, 12:38:14 PM9/23/09
to nunit-...@googlegroups.com
Hmm... I can more or less do the same today without a separate method:

EventArgs blahEventArgs = null;
blah.Closed += (sender, e) => blahEventArgs = e;
blah.RaiseClosed(1);
Assert.IsNotNull(blahEventArgs);

This works with any kind of events, not just EventHandler type of events.

That being said, I admit that your approach is cleaner for
EventHandler<T> type of events. The only issue is the string event
name that may break in refactoring.

BTW, I liked your blog, especially the clean look of pasted source
code. Would you mind to share which blogging client you use and how
you paste code in nice HTML?

Thanks,
Kenneth

markheath

unread,
Sep 23, 2009, 1:13:10 PM9/23/09
to NUnit-Discuss
Hi Kenneth,
good point. I had a feeling I might be missing something really
obvious ;)

I'm using InsertCodePlugin for LiveWriter
I think it's this one:
http://gallery.live.com/liveItemDetail.aspx?li=1f57bd9b-a692-4593-9e9e-e2962d9c0eee

Mark

On Sep 23, 5:38 pm, Kenneth Xu <kenne...@gmail.com> wrote:
> Hmm... I can more or less do the same today without a separate method:
>
>             EventArgs blahEventArgs = null;
>             blah.Closed += (sender, e) => blahEventArgs = e;
>             blah.RaiseClosed(1);
>             Assert.IsNotNull(blahEventArgs);
>
> This works with any kind of events, not just EventHandler type of events.
>
> That being said, I admit that your approach is cleaner for
> EventHandler<T> type of events. The only issue is the string event
> name that may break in refactoring.
>
> BTW, I liked your blog, especially the clean look of pasted source
> code. Would you mind to share which blogging client you use and how
> you paste code in nice HTML?
>
> Thanks,
> Kenneth
>
> On Wed, Sep 23, 2009 at 10:46 AM, markheath <mark.he...@gmail.com> wrote:
>
> > I've blogged my best effort at creating an Assert.Raises method here:
> >http://mark-dot-net.blogspot.com/2009/09/asserting-events-with-nunit....

Charlie Poole

unread,
Sep 23, 2009, 10:23:38 PM9/23/09
to nunit-...@googlegroups.com
Hi Kenneth,

> For exception property you can use:
>
> InvalidOperationException e = (
> Assert.Throws<InvalidOperationException>(() =>
> objectUnderTest.DoSomething()); Assert.AreEqual("My Test
> Message", e.Message);

Alternatively...

Assert.That( () => objectUnderTest.DoSomething,
Throws<InvalidOperationException>().Message.EqualTo("My Test Message");

Charlie

Charlie Poole

unread,
Sep 24, 2009, 2:31:17 AM9/24/09
to nunit-...@googlegroups.com
Hi Mark,

This looks like it could lead to an interesting NUnit addition.
I'd like to consider an alternate, constraint-based syntax
similar to Throws....

Assert.That( () => someObject.SomeMethod()
Raises...

where ... represents something we have yet to invent. :-)

Possibilities...

* A delegate or lambda
* An Event type
* Cascaded constraints as with Throws
* ???



Charlie

> -----Original Message-----
> From: nunit-...@googlegroups.com
> [mailto:nunit-...@googlegroups.com] On Behalf Of markheath
> Sent: Wednesday, September 23, 2009 7:47 AM
> To: NUnit-Discuss
> Subject: [nunit-discuss] Re: Feature request: Assert.Raises,
> better Assert.Throws
>
>

Sébastien Lorion

unread,
Sep 24, 2009, 10:41:47 AM9/24/09
to nunit-...@googlegroups.com
Btw, since you asked about showing code in html, you may want to take
a look at SyntaxHighlighter:

http://alexgorbatchev.com/wiki/SyntaxHighlighter

Sébastien

Kenneth Xu

unread,
Sep 24, 2009, 10:15:18 PM9/24/09
to nunit-...@googlegroups.com
Hi Charlie,

> Assert.That( () => objectUnderTest.DoSomething,
>   Throws<InvalidOperationException>().Message.EqualTo("My Test Message");

Is this something in future or I missed. I don't see a Throws<T>
class. Or may be you meant

Assert.That(() => { throw new InvalidOperationException("aaa"); },

Throws.InvalidOperationException.With.Message.EqualTo("aaa"));

Yes, that reads very nicely. Maybe I was lazy and I should really
spend sometime digest all the properties of With and nested With and
so on. I feel it is not intuitive of when and what is applicable.

Cheers,
Kenneth

Kenneth Xu

unread,
Sep 24, 2009, 10:31:34 PM9/24/09
to nunit-...@googlegroups.com
Hi Sebastien,

> http://alexgorbatchev.com/wiki/SyntaxHighlighter

Thanks for the info. I had been at
http://developertips.blogspot.com/2007/08/syntaxhighlighter-on-blogger.html.
Looks very nice but it still requires me to manually insert <pre> and
replace < with &lt;. Not that I cannot deal with HTML and CSS, I guess
I'm too lazy or I want everything just quick.

I need copy, past and publish type of thing that looks OK, not
necessary perfect so Mark's fit me better.

That being said, I do appreciate your help and thanks again.

Cheers,
Kenneth

Kenneth Xu

unread,
Sep 24, 2009, 10:38:23 PM9/24/09
to nunit-...@googlegroups.com
Hi Charlie,

>   Assert.That( () => someObject.SomeMethod()
>      Raises...

This syntax looks nice for simply asserts. But become hard and verbose
when I need to assert various things.

In the case of ArgumentException, I usually assert message and
ParamName so I find myself use Assert.Throws and Assert.Catch more
often.

In order to work with event of any delegate type. The return value
should contains all the parameters of a delegate. In Mark's example,
what if I also need to assert the sender?

I believe linq/anonymous class will be useful here.

Cheers,
Kenneth

Charlie Poole

unread,
Sep 24, 2009, 10:41:39 PM9/24/09
to nunit-...@googlegroups.com
Hi Kenneth,

You're right, that was email code. :-) But the corrected syntax
you provided works.

Throws is particularly confusing, which led to the creation of
the alternate Assert.Throws syntax. But the existence of alternate
ways of doing something is confusing in itself.

Charlie

> -----Original Message-----
> From: nunit-...@googlegroups.com
> [mailto:nunit-...@googlegroups.com] On Behalf Of Kenneth Xu
> Sent: Thursday, September 24, 2009 7:15 PM
> To: nunit-...@googlegroups.com
> Subject: [nunit-discuss] Re: Feature request: Assert.Raises,
> better Assert.Throws
>
>

Charlie Poole

unread,
Sep 25, 2009, 9:42:23 AM9/25/09
to nunit-...@googlegroups.com
Hi Kenneth,

> >   Assert.That( () => someObject.SomeMethod()
> >      Raises...
>
> This syntax looks nice for simply asserts. But become hard
> and verbose when I need to assert various things.
>
> In the case of ArgumentException, I usually assert message
> and ParamName so I find myself use Assert.Throws and
> Assert.Catch more often.

Well, that's what the three dots was supposed to represent. :-)

In the case of ArgumentException, you might use

Throws.ArgumentException.Message.EqualTo("xxxx")
.Property("ParamName").EqualTo("yyyy")

(The quotes are needed for ParamName because it's not known to
the syntax - although it could be)

> In order to work with event of any delegate type. The return
> value should contains all the parameters of a delegate. In
> Mark's example, what if I also need to assert the sender?

That's only true using an approach similar to Assert.Throws,
which returns the value for further testing. I'm thinking
that it may be a better approach to accommodate all the tests
in a single call.

> I believe linq/anonymous class will be useful here.

I think that's one of the ways we could fill in the three
dots - there may be others.

Charlie
> Cheers,
> Kenneth
>
> >
>


Kenneth Xu

unread,
Sep 25, 2009, 12:16:37 PM9/25/09
to nunit-...@googlegroups.com
Hi Charlie,

>  Throws.ArgumentException.Message.EqualTo("xxxx")
>        .Property("ParamName").EqualTo("yyyy")

Interesting! As I said I need to spend sometime to this. But still, I
don't really see it is better then Assert.Catch approach. The biggest
issue with Throws constraint is that I lost direct access to exception
object so it becomes difficult for complex evaluation of the
exception. And yes the string name of property is reminding me the
time I migrate off NMock2.

Cheers,
Kenneth

Charlie Poole

unread,
Sep 26, 2009, 10:48:40 PM9/26/09
to nunit-...@googlegroups.com
Hi Kenneth,
Yes. Of course, we could add ParamName as a field that the
current implementation understands, but that's limiting.

Remember, however, that all of this is to be extended to
use lambdas in 3.0. That should solve many of the problems.

That said, Assert.Catch offers an alternative that some
people will continue to prefer.

I'm not sure, however, how to extend this to events in
the same style, without building in assumptions about
the event arguments.

Charlie
> Cheers,
> Kenneth
>
> >
>



click...@gmail.com

unread,
Apr 20, 2014, 4:24:10 AM4/20/14
to nunit-...@googlegroups.com, cha...@nunit.com
Did you make any headway on this?  I looked through the 3.0 specs and didn't see any references to events.  Your suggested constraint-based syntax, together with Mark's blog code, would be so useful in our product testing where we have background workers for certain long-running tasks, asynchronous network data arriving as well as UI testing (can we "cancel" any of these operations cleanly?).

Sure, it's much more than mere unit testing, but isn't that the vision?

Rick

Charlie Poole

unread,
Apr 21, 2014, 9:02:28 AM4/21/14
to click...@gmail.com, nunit-...@googlegroups.com
Originally, this struck me as a fairly decent idea, and I encouraged
it, but nobody outside of the original poster seemed to need it - or
at least they didn't say so - and no issue was ever filed.

In my own code, I either use NSubstitute to mock the receiver of the
event or if it's more convenient, simply register a lambda to capture
the event. I haven't found a need for more than that, so it's not
something I want personally.

I would like to see a bit of interest in this from others before
considering it as a new feature. The details of the feature can be
worked out later, but my first question is about whether a feature is
really needed, given that it's fairly trivial to test for the
generation of events without it. [Testing how events are handled is
another matter, of course.]

Of course, you can propose it as a new feature at
http://github.com/nunit/nunit-framework, but I think you'll do better
if you can raise some interest here first.

Charlie
Reply all
Reply to author
Forward
0 new messages