I have a code for catching SqlException. I wrote a test to handle SQLException based on answer listed here: How to throw a SqlException when needed for mocking and unit testing?
[TestMethod]
public async Task TestFailJobOnSqlExceptionAsync()
{
_context.Setup(x => x.CallSubOrchestratorAsync()
.Throws(MakeSqlException());
var orchestratorFunction = new OrchestratorFunction(_configuration.Object, _loggingRepository.Object);
await orchestratorFunction.RunOrchestratorAsync(_context.Object, _executionContext.Object);
_log.Verify(x => x.LogMessageAsync(
It.Is<LogMessage>(m => m.Message.StartsWith($"Caught SqlException")),
It.IsAny<VerbosityLevel>(),
It.IsAny<string>(),
It.IsAny<string>()), Times.Never());
}
public static SqlException MakeSqlException()
{
SqlException exception = null;
try
{
SqlConnection conn = new SqlConnection(@"Data Source=.;Database=GUARANTEED_TO_FAIL;Connection Timeout=1");
conn.Open();
}
catch (SqlException ex)
{
exception = ex;
}
return (exception);
}
On running this, my test fails with error
Test method Services.Tests.TestFailJobOnSqlExceptionAsync threw exception: Microsoft.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) ---> System.ComponentModel.Win32Exception: The system cannot find the file specified.
What am I missing?
When writing unit-tests where you want to assert that a certain exception is thrown, you'll use the
[ExpectedException(typeof(Microsoft.Data.SqlClient.SqlException))]attribute above the test.When the attribute is missing the test fails because the test framework does not understand you're expecting the exception.
If you want to verify that the logger is called, you'll need to write a try catch block around the setup up till the verify method.