I’m using xUnit, SubSpec and FakeItEasy for my unit tests. I’ve so far created some positive unit tests like the following:
"Given a Options presenter"
.Context(() =>
presenter = new OptionsPresenter(view,
A<IOptionsModel>.Ignored,
service));
"with the Initialize method called to retrieve the option values"
.Do(() =>
presenter.Initialize());
"expect the view not to be null"
.Observation(() =>
Assert.NotNull(view));
"expect the view AutoSave property to be true"
.Observation(() => Assert.True(view.AutoSave));
But now I want to write some negative unit tests and check that certain methods don't get called, and an exception is thrown
e.g.
"Given a Options presenter"
.Context(() =>
presenter = new OptionsPresenter(view,
A<IOptionsModel>.Ignored,
service));
"with the Save method called to save the option values"
.Do(() =>
presenter.Save());
"expect an ValidationException to be thrown"
.Observation(() =>
// TODO
);
"expect an service.SaveOptions method not to be called"
.Observation(() =>
// TODO
);
I can see FakeItEasy has a MustNotHaveHappened extension method, and xUnit has an Assert.Throws method.
But how do I put it all together?
The exception I want to test for should occur when the Save method is called. So I’m guessing I should wrap an Assert.Throws method around the presenter.Save() method call, but I thought the presenter.Save method should be called in the .Do(() => ...
Can you please advise if my unit test should look like below or something else?
"Given a Options presenter"
.Context(() =>
presenter = new OptionsPresenter(view,
model,
service));
"expect the Presenter.Save call to throw an Exception"
.Observation(() =>
Assert.Throws<FluentValidation.ValidationException>(() => presenter.Save()));
"expect the Service.SaveOptions method not to be called"
.Observation(() =>
A.CallTo(() => service.SaveOptions(A<IOptionsModel>.Ignored)).MustNotHaveHappened());
Many thanks
xUnit uses Assert. Throws to test for exception types. You could catch the exception and Assert against the message if you needed. I think in general you want to test that the expected exception is thrown, and the exact message is really not necessary.
The HandleError Error attribute has a couple for properties that are very useful in handling the exception. ExceptionType: Type of exception to be catch. If this property is not specified then the HandleError filter handles all exceptions.
I've not heard of FakeItEasy or SubSpec (your tests look pretty funky, so I might check these out :)). However, I do use xUnit so this may be helpful:
I use Record.Exception with Assert.ThrowsDelegate
So something like:
[Fact]
public void Test()
{
// Arange
// Act
Exception ex = Record.Exception(new Assert.ThrowsDelegate(() => { service.DoStuff(); }));
// Assert
Assert.IsType(typeof(<whatever exception type you are looking for>), ex);
Assert.Equal("<whatever message text you are looking for>", ex.Message);
}
Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With