11

I want to write Unit test cases for following code

HomeController.cs

[HttpPost]
        [ActionName("CreateDemo")]
        public async Task<IHttpActionResult> CreateDemo([FromBody] MyRequest request)
        {
            if (request == null)
            {                    
                return BadRequest("request can not be null");
            }
            if (request.MyID == Guid.Empty)
            {
                return BadRequest("MyID must be provided");
            }
        }

I tried like following which is not correct way i guess so

 [TestMethod]
        public async Task NullCheck()
        {
            try
            {
                var controller = new HomeController();
                var resposne = await controller.CreateDemo(null);
                Assert.AreEqual(); // not sure what to put here
            }
            catch (HttpResponseException ex) //catch is not hit
            {
                Assert.IsTrue(
                     ex.Message.Contains("request can not be null"));
            }

        }
Neo
  • 15,491
  • 59
  • 215
  • 405

1 Answers1

10

Each unit test shall test one requirement or concern. Your method implements two requirements:

1) If request is null, return BadRequestErrorMessageResult object with predefined error message. 2) If request's MyID property is empty GUID, return BadRequestErrorMessageResult object with another predefined error message.

This means we should have two unit tests:

[Test]
public async Task CreateDemo_returns_BadRequestErrorMessageResult_when_request_is_null()
{
   // Arrange
   var controller = new HomeController();

   // Act
   var response = await controller.CreateDemo(null);

   // Assert
   Assert.IsInstanceOf<BadRequestErrorMessageResult>(response);
   Assert.AreEqual("request can not be null", response.Message);
}

[Test]
public async Task CreateDemo_returns_BadRequestErrorMessageResult_when_request_ID_is_empty_GUID()
{
   // Arrange
   var controller = new HomeController();
   var request = new MyRequest(Guid.Empty);

   // Act
   var response = await controller.CreateDemo(request);

   // Assert
   Assert.IsInstanceOf<BadRequestErrorMessageResult>(response);
   Assert.AreEqual("MyID must be provided", response.Message);
}

You can go even further and split each of these tests into two where one would test that return object is of the expected type and another that validates that returned object state is as expected (e.g. Message string is as expected). This way you would have a single assert per test.

Side notes:

You tagged this question with nunit tag so I provided the code which uses that framework. In your example though, you use [TestMethod] attribute which comes from Microsoft unit testing framework. If you want to use that framework you'd have to make some changes e.g. replace Assert.IsInstanceOf with Assert.IsInstanceOfType.

I assumed that GUID is passed to MyRequest via its constructor which assigns it to MyID.

I am not coming from web world but I found that BadRequest method has an overload which returns BadRequestErrorMessageResult if string is passed as its argument.

Bojan Komazec
  • 9,216
  • 2
  • 41
  • 51
  • thanks , how to use `IsInstanceOfType` to compare message? – Neo Aug 24 '16 at 07:31
  • For string assertions, use `Assert.AreEqual` or, as Nunit3 [advises](https://github.com/nunit/docs/wiki/EqualConstraint), use constraint model with Equal constraint: `Assert.That(response.Message, Is.EqualTo("MyID must be provided"));` – Bojan Komazec Aug 24 '16 at 07:49
  • 3
    I would assume it would work the same for XUnit? But It seems to me that the `Assert`doesn't have `IsInstanceOf` in the XUnit framework... – superninja Apr 19 '18 at 05:18