Richard210363
Richard210363

Reputation: 8406

Why can't I detect this Exception in my Tests

I am writing an Intigration test using nUnit in C#.

My code is:

public async Task<bool> WriteData(Document data, string tableName)
{
   try
   {
      var table = Table.LoadTable(_dynamoDbClient, tableName);
      table.PutItem(data);
      return true;
   }
   catch (Exception e)
   {
     _logger.Info("Failed Writing Record");
     _logger.Info("Error: " + e.Message);
     return false;
   }
}

My Test is:

public void TestToSeeIfWeGetAnExceptionWhenProvidingBadDataToTheDatabase()
{
   // arrange
   var item = new Document
   {
      ["Id"] = "1001",
      ["TransactionID"] = 111111,
      ["StatementType"] = "TestBank"
   };

   _bankStatementTable = "does-not-exist";

   // act / assert

   Assert.Catch<System.Exception>(() => _awsDynamoDbManager.WriteData(item, _bankStatementTable));
}

Because I am passing bad data to the database I expect an exception and I get one.
However, the test fails. I get this message from the test runner:

Expected: instance of <System.Exception>

But was: null

If I run the test in Debug I can see the Catch being hit. What am I missing?

Upvotes: 0

Views: 106

Answers (2)

Pavel Anikhouski
Pavel Anikhouski

Reputation: 23228

You should update your code a little bit. Rethrow an Exception in catch block and use ThrowsAsync

catch (Exception e)
{
     _logger.Info("Failed Writing Record");
     _logger.Info("Error: " + e.Message);
     throw;
}
...
Assert.ThrowsAsync<System.Exception>(async () => await _awsDynamoDbManager.WriteData(item, _bankStatementTable));

Or check that WriteData returns false by making test as async as well and call Assert.IsFalse

public async Task TestToSeeIfWeGetAnExceptionWhenProvidingBadDataToTheDatabase()
{
   // arrange
   ...
   // act / assert

   var result = await _awsDynamoDbManager.WriteData(item, _bankStatementTable);
   Assert.IsFalse(result);
}

Since there is no awaitable code inside WriteData method, you can make it synchronous one and use Task.FromResult as return result or make it even simpler and remove using of Task<bool>

public bool WriteData(Document data, string tableName)
{
   try
   {
      var table = Table.LoadTable(_dynamoDbClient, tableName);
      table.PutItem(data);
      return true;
   }
   catch (Exception e)
   {
     _logger.Info("Failed Writing Record");
     _logger.Info("Error: " + e.Message);
     return false; //or throw;
   }
}

And the synchronous test code

Assert.Throws<System.Exception>(() => _awsDynamoDbManager.WriteData(item, _bankStatementTable));

or

public void TestToSeeIfWeGetAnExceptionWhenProvidingBadDataToTheDatabase()
{
   // arrange
   ...
   // act / assert

   var result = _awsDynamoDbManager.WriteData(item, _bankStatementTable);
   Assert.IsFalse(result);
}

Upvotes: 2

Alexbogs
Alexbogs

Reputation: 400

Because you are returning false in case of Exception:

catch (Exception e)
{
    _logger.Info("Failed Writing Record");
    _logger.Info("Error: " + e.Message);
    return false;
}

Use throw clause.

Upvotes: 0

Related Questions