Unit testing, using Moq to verify the exception message
It doesn't match because the two exceptions you compare aren't the same instance of Exception.
You can check if the message part of the Exception is what you want by passing in a lambda expression like this
services.MockLogProvider.Verify(x => x.LogExceptionAsync(
It.Is<Exception>(e => e.Message == "Order doesn't exist on ERP"),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<Dictionary<string, string>>(),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<int>()));
Moq fails to throw exception in Unit Test
If an invoked mock does not behave as expected, most times it is because the setup did not match what was actually invoked.
Consider loosening the expectation using It.IsAny<T>()
Fact(DisplayName = "AddUserSettingsAsync - InvalidOperationException")]
[Trait("Category", "Unit Test")]
public async Task SettingsStoreAddUserSettingsTestWithException() {
//Arrange
string userObject = Guid.NewGuid().ToString();
string correlationId = Guid.NewGuid().ToString();
string body = File.ReadAllText("TestData/userSettings.json");
UserSettingsObject userSettingsObject = JsonConvert.DeserializeObject<UserSettingsObject>(body);
var iFunctionEnvironment = TestHelpers.GetEnvironmentVariable("Test");
Uri.TryCreate("http://localhost", UriKind.Absolute, out Uri uri);
var iblobStorageRepositoryMoq = new Mock<IBlobStorageRepository>();
iblobStorageRepositoryMoq
.Setup(mock => mock.Add(It.IsAny<ILogger>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.ThrowsAsync(new InvalidOperationException("Function Add threw an exception"));
//The SUT
var subjectUnderTest = new SettingsStore(iFunctionEnvironment, iblobStorageRepositoryMoq.Object);
//Act
InvalidOperationException exception = await Assert.ThrowsAsync<InvalidOperationException>(() => subjectUnderTest.AddUserSettingsAsync(logger, correlationId, userSettingsObject, userObject));
//Assert
Assert.Equal("Function Add threw an exception", exception.Message);
Assert.Null(exception.InnerException);
}
Note the change to the setup and also if asserting that InvalidOperationException
was thrown then mock should actually throw an InvalidOperationException
//...
var iblobStorageRepositoryMoq = new Mock<IBlobStorageRepository>();
iblobStorageRepositoryMoq
.Setup(mock => mock.Add(It.IsAny<ILogger>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.ThrowsAsync(new InvalidOperationException("Function Add threw an exception"));
//...
Correct method for testing for an exception using Moq and MSTest
You are right - the second test "SaveCart" works because it's throwing an exception and the the first test fail because you are turning 0. From your response to previous answers, I am sure you already know all of this. If you are asking for the behavior how it failed your first test... it goes like this:
- SaveCart is called
- It returns an exception (result of your moq setup)
- Your try catch caught the exception (you did this on purpose to alter the result)
- Your try catch returns 0 (result is now 0 as you intended to alter it)
- Assert checks your result against _cartSaveExceptionValue
- You get a fail test stating something similar to this "Message: Assert.AreEqual failed. Expected. Actual<0 (System.Int32)>."
If you want to double check this... you can try the following test
- comment out the [ExpectedException(typeof())]
- change the Assert.AreEqual(result, _cartSaveExceptionValue) to Assert.AreEqual(result, 0);
- the test should pass because you are comparing "result" (aka 0) to 0
I hope this answer your question.
How can I throw Exception for async function using Moq
Considering the asynchronous nature of the code under test, it would be better if the test code be asynchronous as well. Moq is async capable
[Fact]
public async Task CreateCSVFile_Failure() {
//Arrange
var dtData = new DataTable();
string fileName = "";
var mockClient = new Mock<IHttpHandler>();
this._iADLS_Operations = new ADLS_Operations(mockClient.Object);
mockClient
.Setup(repo => repo.PostAsync(It.IsAny<string>(), It.IsAny<HttpContent>(), It.IsAny<string>()))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.BadRequest));
mockClient
.Setup(repo => repo.SendAsync(It.IsAny<HttpRequestMessage>(), It.IsAny<string>()))
.ThrowsAsync(new Exception("Some message here"));
//Act
Func<Task> act = () => this._iADLS_Operations.CreateCSVFile(dtData, fileName);
//Assert
Exception ex = await Assert.ThrowsAsync<Exception>(act);
Assert.Contains("Exception occurred while executing method:", ex.Message);
}
Note the use of Moq's ReturnsAsync
and ThrowsAsync
in the setup, along with xUnit's Assert.ThrowsAsync
This now allows you to avoid making blocking calls like .Result
which could potentially lead to deadlocks.
Moq throwing NullReferenceException on Verify with It.Is but not It.IsAny
money.Amount == 0
If money is null, it won't be able to evaluate this and I'd expect a null reference exception.
Changing it to handle the null case should sort it out if that's your issue
It.Is<MoneyWorks.Money>(money => money != null && money.Amount == 0)
Related Topics
Remove Surrounding Whitespace from an Image
How to Return a File (Filecontentresult) in ASP.NET Webapi
Merge Multiple Lists into One List With Linq
How to Make a Soap/Wsdl Client in C#
C# Check the Empty or Null Value in All Datatable Values
How to Download Image from Url
Sending Array of Bytes from Client to Server
How to Upload File to Server With Http Post Multipart/Form-Data
Asp.Net Core Identity Successful Login Redirecting Back to Login Page
How to Calculate Sum (Total) of Datatable Columns Using C#
Convert Byte Array to Wav File
Cannot Access a Closed Stream of a Memorystream, How to Reopen
How to Store List of Data from Database to Arraylist or List in C#
Converting Datetime C# Type to Date JavaScript in ASP.NET MVC Razor Application
Automatic Enhancement of Scanned Images
Create a C# Method to Generate Auto Increment Id
Build Query String for System.Net.Httpclient Get
How to Cast Object to List<Object> and Turn It into an Array