2

My service class methode is

public async ValueTask<HttpResponseMessage> UploadFileAsync(string fileKey)
{
  ..
  var multipartContent = new MultipartFormDataContent();
  multipartContent.Add(httpContent, "upfile", Path.GetFileName(fileKey));
  //in negative test case I am sending empty fileKey value then throwing argument exception from here
  ..
  return httpResponseMessage;
}

I am calling this value task fileupload method in my test case like below

[Fact]
public async Task UploadFileAsync_WhenFileKeyParameterIsEmpty_ReturnArguementException()
{
     string fileKey = "";
     var ex = Assert.ThrowsAsync<ArgumentException>(()=>objHttpService.UploadFileAsync(fileKey)); 
     Assert.Equal("The value cannot be null or empty. (Parameter 'fileName')", ex.Message);
}

I couldn't able to get any response in ex variable, and getting assert failure like below.

Message:  Assert.Throws() Failure Expected: typeof(System.ArgumentException) Actual: (No exception was thrown)

Ahmed
  • 115
  • 7
  • 1
    Does the answer here help? https://stackoverflow.com/questions/14084923/how-to-handle-exceptions-thrown-by-tasks-in-xunit-nets-assert-throwst – Klaus Gütter Dec 08 '22 at 14:10

2 Answers2

1
var ex = await Assert.ThrowsAsync<ArgumentException>(
    () => objHttpService.UploadFileAsync(fileKey));

The Throws version would only detect problems if the async API threw synchronously, rather than the more typical behaviour of synchronously or asynchronously returning a faulted value-task.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
1

You have two issues. Firstly because your code is async you need to use xUnit's ThrowsAsync method and await the result.

Secondly ThrowsAsync expects a Func<Task> as a parameter, and () => UploadFileAsync(fileKey) is a Func<ValueTask>. We can get around this by calling AsTask() on the result of the call to UploadFileAsync. So we need to change the call to Assert.Throws to:

var ex = await Assert.ThrowsAsync<ArgumentException>(
    () => objHttpService.UploadFileAsync(fileKey).AsTask());

Working test code is below. Note that UploadFileAsync is just a test stub that should behave like the method you are testing.

public class objHttpService
{
    [Fact]
    public async Task UploadFileAsync_WhenFileKeyParameterIsEmpty_ReturnArguementException()
    {
        string fileKey = "";
        var ex = await Assert.ThrowsAsync<ArgumentException>(
            () => objHttpService.UploadFileAsync(fileKey).AsTask());
        Assert.Equal("The value cannot be null or empty. (Parameter 'fileName')", ex.Message);
    }

    // Test code only - existing method shouldn't need to be changed
    public static async ValueTask<HttpResponseMessage> UploadFileAsync(string _)
    {
        await Task.Delay(10);
        throw new ArgumentException("The value cannot be null or empty. (Parameter 'fileName')");
    }
}
Rich N
  • 8,939
  • 3
  • 26
  • 33
  • yeah, actually I tried with ThrowsAsync only, but was missed to write here, but after I added ".AsTask()", then the debug issue is gone but my debugger get stopped and get succeed that test case but still I couldn't get exception message and couldn't assert.equal(stringval,ex.message), and for await Task.Delay(10); I don't have permission to change service code. – Ahmed Dec 09 '22 at 06:13
  • I've confused you by including my test code, I think. The only change you should need to make is the line `var ex = await Assert.ThrowsAsync( () => objHttpService.UploadFileAsync(fileKey).AsTask());`. UploadFileAsync shouldn't need to be changed, you don't need `await Task.Delay(10)` . The test code above works in a new xUnit Test Project in VS2022 if you just paste the whole class in, but obviously I don't have your code for UploadFileAsync so have created my own mock. – Rich N Dec 09 '22 at 10:58
  • So are you saying you change the line to use AsTask and then debug the test then it always passes and won't break on Assert.Equal? Or that it doesn't have the right message when it gets to Assert.Equal? What you've said isn't clear. – Rich N Dec 09 '22 at 11:01
  • sorry, I mean even I remove Task.Delay(10), so as per you mentioned code var ex = await Assert.ThrowsAsync( () => objHttpService.UploadFileAsync(fileKey).AsTask()); also couldn't working for caching the message in result and debugger auto get stoped and not ran asserts which after written. but test case looks succeed by green marked. – Ahmed Dec 13 '22 at 09:42