4

I am new to C# unit testing and have to test if the method is working properly.

Here is what I have so far:

  public async Task<IHttpActionResult> Post(API_FIRM_LINK aPI_FIRM_LINK)
    {
        db.API_FIRM_LINK.Add(aPI_FIRM_LINK);
        await db.SaveChangesAsync();

        return Created(aPI_FIRM_LINK);
    }

test method: Not really sure if I am on the right path If someone could provide an example based on my test

     public async Task PostTest()

    {
        ////Arrange
        API_FIRM_LINKController controller = new API_FIRM_LINKController();

        API_FIRM_LINK aPI_FIRM_LINK = null;

        IHttpActionResult expectedResult = await controller.Post(aPI_FIRM_LINK);
        //act

        IHttpActionResult result = await controller.Post(API_FIRM_LINK, aPI_FIRM_LINK);


        ////Assert
        IComparer<IHttpActionResult> comparer = new IHttpActionResultComparer();
       // Assert.IsTrue(comparer.Equals(expectedResult, result));

        Assert.IsNotNull(result);
        Console.Write(result);
usertestREACT
  • 263
  • 2
  • 7
  • 15

2 Answers2

7

If you use a modern version of Microsoft.VisualStudio.TestTools.UnitTesting you can use an async test method, like you do in your question.

If you want to Test whether your Post function returns the expected data, do the following:

[TestMethod()]
public async Task PostTestAsync()
{
    var controller = new API_FIRM_LINKController();
    // TODO: do some preparations, so you can expect a specific return value
    IHttpActionResult expectedResult = ...

    // call PostAsync and await for it to finish
    Task taskPost =  controller.PostAsync(API_FIRM_LINK, aPI_FIRM_LINK);
    IHttpActionResult result = await taskPost;

    // of course this can be done in one line:
    IHttpActionResult result = await controller.PostAsync(API_FIRM_LINK, aPI_FIRM_LINK);

    // compare whether result equals expectedResult
    // for example: create a class that implements IComparer<IHttpActionResult>
    IComparer<IHttpActionResult> comparer = new IHttpActionResultComparer();
    Assert.IsTrue(comparer.Equals(expectedResult, result);
}

If you use a test suite where you can't use async tests:

[TestMethod()]
public void PostTest()
{
    var controller = new API_FIRM_LINKController();
    IHttpActionResult expectedResult = ...

    // call PostAsync and wait for it to finish
    Task taskPost =  Task.Run(() => controller.PostAsync(API_FIRM_LINK, aPI_FIRM_LINK));
    taskPost.Wait();
    IHttpActionResult result = taskPost.Result;

    // TODO: compare result with expected result
}
Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116
  • I tried to make some adjustments since most of it was breaking and not able to build it. await controller.PostAsync(API_FIRM_LINK, aPI_FIRM_LINK) get the following message: API_FIRM_LINK is a type - not valid . and aPI_FIRM_LINK does not exist. – usertestREACT Mar 12 '19 at 13:15
  • I only copy-pasted the call to method Post from the code in your question. The only change I made was rename it to PostAsync, to match the more common name of an async function. I assumed you knew how to program and could see through this small change. Of course you should use Post if your code is called Post! – Harald Coppoolse Mar 12 '19 at 15:06
  • I am new to it..so I am doing some research on it. Thanks for the help – usertestREACT Mar 12 '19 at 15:13
  • 1
    This "async Task" solved my problem trying for 2 hours. Actually failed to identify where the problem is. Thank you very much Harald. – agileDev May 20 '20 at 09:11
5

Never async void, basically.

[TestMethod]
public async Task PostTest() {...}

If your testing framework doesn't support Task tests: change testing framework.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • But how could I write a test that check if it works correctly or not - – usertestREACT Mar 11 '19 at 17:29
  • 1
    @usertestREACT `await Task.Delay(500); Assert.Fail();` - if it doesn't fail, it isn't working – Marc Gravell Mar 11 '19 at 17:52
  • await controller.Post(API_FIRM_LINK aPI_FIRM_LINK); error here: API_FIRM_LINK is a type which is not valid in the given context – usertestREACT Mar 11 '19 at 17:55
  • Console result = System.Threading.Tasks.Task'1{System.Web.Http.IHttoActionResult ] so far – usertestREACT Mar 11 '19 at 19:02
  • @MarcGravell what's the downside of using `async void` on a `[TestMethod]`? – Muhammad Mamoor Khan Aug 11 '22 at 10:58
  • @MuhammadMamoorKhan the test runner doesn't know when the operation has completed, so could incorrectly report a test as successful, when it is still running asynchronously and could still fail; consider: `[TestMethod] public async void Simple() { await Task.Yield(); Assert.Fail(); }` - now make it `async Task` and it works correctly (i.e. reports failure) – Marc Gravell Aug 11 '22 at 14:23