3

I have a function which saves to a couch db database and it is a Task Void method, it does not return anything and I want to unit test that, but it gives the error I am not expecting...

I've tried Asserting that the return is a Task type but it doesn't work

public async Task CreateMessageHistoryAsync(Message message)
{
  //This is the method that I am testing
    if (!response.IsSuccessStatusCode)
        {
            throw new HttpRequestException(await response.Content.ReadAsStringAsync());
        }
    //This will throw if it does not save, can I test this?
}



[Fact]
public async Task Should_NotThrowHttpRequestException_When_AMessageHistoryIsCreated()
{
  var recipients = MockMessage.GetRecipients("Acc", "Site 1", "Site 2", "Site 3");
  var message = MockMessage.GetMessage(recipients);

  mockStateFixture
    .MockMessageHistoryService
    .Setup(service => service.CreateMessageHistoryAsync(message));                    

  var messageHistoryService = new MessageHistoryService(
                mockStateFixture.MockIHttpClientFactory.Object);

  await Assert.IsType<Task>(messageHistoryService.CreateMessageHistoryAsync(message));              
}

I expect a task to return but this is the actual results:

Result Message:

Assert.IsType() Failure
Expected: System.Threading.Tasks.Task
Actual:   System.Threading.Tasks.Task`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]
Ivan Apungan
  • 534
  • 6
  • 17
  • Please read this post https://stackoverflow.com/questions/17824863/what-is-the-type-voidtaskresult-as-it-relates-to-async-methods. These types differs... – Johnny Jan 15 '19 at 11:36
  • @Johnny I see so they're different, how do I assert that it returns a VoidTaskResult? – Ivan Apungan Jan 15 '19 at 11:39
  • I do know one way which is not really elegant but maybe can help: `Assert.Equal("System.Threading.Tasks.VoidTaskResult", messageHistoryService.CreateMessageHistoryAsync(message).GetType().GetProperty("Result")?.GetMethod.Invoke(t, new object[] { })?.GetType().FullName);` – Johnny Jan 15 '19 at 13:25

1 Answers1

4

The Task returned from your async method is generated by the compiler. It may be an instance of Task, or it may be an instance of a derived type. And this may change with future updates. You don't want to check specifically for the Task type; that would tie your unit test to an implementation detail.

You could test for "is this Task or a derived type?", which looks like await Assert.IsAssignableFrom<Task>(messageHistoryService.CreateMessageHistoryAsync(message));

However, I don't think that's a useful assertion at all. It's not useful to assert that a method returning T actually returns a T (or derived type), because of course it returns T! So, I would recommend removing that assertion completely: await messageHistoryService.CreateMessageHistoryAsync(message);

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810