0

I am writing a lot of test to test negative scenarios so basically when a task fails I need to check that the right exception type is thrown and that the message is right. What I have tried by Googling is this

public async void TaskToTest_OnFailGiveException()
{
    var info = new Info();

    var ex = await Record.ExceptionAsync(() => info.TaskToTest());

        Assert.NotNull(ex);
        Assert.IsType<Exception>(ex);
}

As well as this to test the message

public void TaskToTest_OnFailGiveException()
{
    var info = new Info();

    var ex = Assert.ThrowsAsync<Exception>(() => info.TaskToTest());

        Assert.NotNull(ex.Exception);
        Assert.Equal(ex.Exception.Message, $"Failed to insert the info");
}

The problem with both of them is that the task doesn't fail so by there it doesn't give any exception to assert against. I know that if I want to mock that a task gives positive return I can to info.TaskToTest().Returns(Task.CompletedTask) but I have failed to find a fail variant of it. Is there any way to make sure that a task fails so I can test the exception?

This is the task I try to make fail

public virtual async Task TaskToTest()
{
    bool result = await _database.InsertOrUpdateInfo(State.InfoID, _unhandledInfo.Count > 0 ? JsonConvert.SerializeObject(_unhandledInfo) : string.Empty);
    if (!result)
    {
        _logger.LogError($"Error while calling InsertOrUpdateInfo. Info: {State.INfoID}");
        var exception = new Exception("Failed to insert the info");
        throw exception;
    }
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
Johan Jönsson
  • 539
  • 1
  • 10
  • 23
  • Does this help? https://stackoverflow.com/questions/40828272/xunit-assert-throwsasync-does-not-work-properly – Renat Jun 18 '19 at 09:42
  • @Renat unfortunatel not since the task is still not failing. The problem is that i need some kind of method to make the TaskToTest fail during this test – Johan Jönsson Jun 18 '19 at 10:53
  • @JohanJönsson you need to mock the database to return `false` so that the method under test flows into the conditional statement that throws the exception. – Nkosi Jun 18 '19 at 12:14

1 Answers1

1

The method under test appears to be making an external call to a database.

You need to mock the database call to return false so that the method under test flows into the conditional statement that throws the exception.

public async Task TaskToTest_OnFailGiveException() {
    //Arrange

    //...mock database and setup accordingly
    //eg: database.InsertOrUpdateInfo(...).ReturnsAsync(false);

    var info = new Info(database);

    //Act
    var ex = await Record.ExceptionAsync(() => info.TaskToTest());

    //Assert
    Assert.NotNull(ex);
    Assert.IsType<Exception>(ex);
}

This should then provide the desired use-case for your test to behave as expected.

Nkosi
  • 235,767
  • 35
  • 427
  • 472