Assert an Exception using XUnit
Solution 1
The Assert.Throws expression will catch the exception and assert the type. You are however calling the method under test outside of the assert expression and thus failing the test case.
[Fact]
public void ProfileRepository_GetSettingsForUserIDWithInvalidArguments_ThrowsArgumentException()
{
//arrange
ProfileRepository profiles = new ProfileRepository();
// act & assert
Assert.Throws<ArgumentException>(() => profiles.GetSettingsForUserID(""));
}
If bent on following AAA you can extract the action into its own variable.
[Fact]
public void ProfileRepository_GetSettingsForUserIDWithInvalidArguments_ThrowsArgumentException()
{
//arrange
ProfileRepository profiles = new ProfileRepository();
//act
Action act = () => profiles.GetSettingsForUserID("");
//assert
ArgumentException exception = Assert.Throws<ArgumentException>(act);
//The thrown exception can be used for even more detailed assertions.
Assert.Equal("expected error message here", exception.Message);
}
Note how the exception can also be used for more detailed assertions
If testing asynchronously, Assert.ThrowsAsync follows similarly to the previously given example, except that the assertion should be awaited,
public async Task Some_Async_Test() {
//...
//Act
Func<Task> act = () => subject.SomeMethodAsync();
//Assert
var exception = await Assert.ThrowsAsync<InvalidOperationException>(act);
//...
}
Solution 2
You could consider something like this if you want to stick to AAA:
// Act
Task act() => handler.Handle(request);
// Assert
await Assert.ThrowsAsync<MyExpectedException>(act);
Solution 3
I think there are two way to handle this scenario which I personally like. Suppose I have below method which I want to test
public class SampleCode
{
public void GetSettingsForUserID(string userid)
{
if (string.IsNullOrWhiteSpace(userid)) throw new ArgumentException("User Id
Cannot be null");
// Some code
}
}
I can test this with below testcase,Make sure you add FluentAssertions nuget in your test project.
public class SampleTest
{
private SampleCode _sut;
public SampleTest()
{
_sut = new SampleCode();
}
[Theory]
[InlineData(null)]
[InlineData(" ")]
public void TestIfValueIsNullorwhiteSpace(string userId)
{
//Act
Action act= ()=> _sut.GetSettingsForUserID(userId);
// Assert
act.Should().ThrowExactly<ArgumentException>().WithMessage("User Id Cannot be null");
}
}
but I found one problem here, whitespace and Null are two different things. c# provides ArgumentException for whitespace and ArgumentNullException for null reference.
So You can refactor your code something like this
public void GetSettingsForUserID(string userid)
{
Guard.Against.NullOrWhiteSpace(userid, nameof(userid));
}
Here you need Ardalis.GuardClauses nuget in your code project And testcase will be something like this
[Fact]
public void TestIfValueIsNull()
{
//Act
Action act = () => _sut.GetSettingsForUserID(null);
//Assert
act.Should().ThrowExactly<ArgumentNullException>().WithMessage("*userId*");
}
[Fact]
public void TestIfValueIsWhiteSpace()
{
//Act
Action act= ()=> _sut.GetSettingsForUserID(" ");
//Assert
act.Should().ThrowExactly<ArgumentException>().WithMessage("*userId*");
}
Solution 4
Instead of following complicated protocols I found it most convenient to use a try catch block :
try
{
var output = Settings.GetResultFromIActionResult<int>(controller.CreateAllFromExternalAPI());
Assert.True(output > 0);
}
catch(InvalidOperationException e)
{
Assert.True("Country table can only be filled from ExternalAPI if table is blank"==e.Message);
}
Related videos on Youtube
wandermonk
Updated on December 09, 2021Comments
-
wandermonk over 2 years
I am a newbie to XUnit and Moq. I have a method which takes string as an argument.How to handle an exception using XUnit.
[Fact] public void ProfileRepository_GetSettingsForUserIDWithInvalidArguments_ThrowsArgumentException() { //arrange ProfileRepository profiles = new ProfileRepository(); //act var result = profiles.GetSettingsForUserID(""); //assert //The below statement is not working as expected. Assert.Throws<ArgumentException>(() => profiles.GetSettingsForUserID("")); }
Method under test
public IEnumerable<Setting> GetSettingsForUserID(string userid) { if (string.IsNullOrWhiteSpace(userid)) throw new ArgumentException("User Id Cannot be null"); var s = profiles.Where(e => e.UserID == userid).SelectMany(e => e.Settings); return s; }
-
Jon Skeet almost 7 yearsWhat do you mean by "is not working as expected"? (Also, please format your code more readably. Use the preview, and post when it looks how you'd want it to look if you were reading it.)
-
Jon Skeet almost 7 yearsHint: you're calling
GetSettingsForUserID("")
before you start callingAssert.Throws
. TheAssert.Throws
call can't help you there. I'd suggest being less rigid about AAA...
-