Search code examples
c#unit-testingdata-annotationsxunit.net

how i can test my data annotation field in core web api?


I try to create the tests for my API controller method. In a simple way, I write the add method.

    [HttpPost]
    [AllowAnonymous]
    public async Task<IActionResult> AddAsync([FromBody]BaseUserDTO dto)
    {
        if (ModelState.IsValid)
        {
            return Ok();
        }
        else
        {
            return ValidationProblem();
        }
    }

in dto model I have

public class BaseUserDTO
{
    [Required(ErrorMessage = "This field should be filled in", AllowEmptyStrings = false)]
    [RegularExpression(@"(^[a-zA-Z0-9_ -]+$)", ErrorMessage = ("Use only Latin characters"))]
    public string FirstName { get; set; }

    [Required(ErrorMessage = "This field should be filled in", AllowEmptyStrings = false)]
    [RegularExpression(@"(^[a-zA-Z0-9_ -]+$)", ErrorMessage = ("Use only Latin characters"))]
    public string LastName { get; set; }
 }

I wrote the first try to test the data annotation

[Fact]
public async Task UserValidationError()
    {
        //Arrange
        BaseUserDTO userDTO = new BaseUserDTO
        {
            FirstName = "222A@@@",
            LastName = "Test",
            Email = "[email protected]",
            PhoneNumber = "(111)111-1111",
            Role = 0,
            Password = "1234567A",
            RetypePassword = "1234567A"
        };

        UserController controller = new UserController(userServicesMock.Object, mapperMock.Object, loggerMock.Object);

        //Act
        IActionResult result = await controller.AddAsync(userDTO);

        //Assert
        Assert.IsType<BadRequestObjectResult>(result);
    }

but the model state always true, and I don't understand why it happened????

My second try take NullReference in mongo connection when startup started (in a normal situation it works good(when the application works), check it by postman)

[Fact]
public async Task UserValidationError(string userState)
    {
        //Arrange
        BaseUserDTO userDTO = new BaseUserDTO
        {
            FirstName = "222A@@@",
            LastName = "Test",
            Email = "[email protected]",
            PhoneNumber = "(111)111-1111",
            Role = 0,
            Password = "1234567A",
            RetypePassword = "1234567A"
        };

        var b = new WebHostBuilder().UseStartup<Startup>().UseEnvironment("development");

        var server = new TestServer(b) { BaseAddress = new Uri(@"http://localhost:54133") };
        var client = server.CreateClient();
        var json = JsonConvert.SerializeObject(userDTO);
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        UserController controller = new UserController(userServicesMock.Object, mapperMock.Object, loggerMock.Object);

        //Act
        var result = await client.PostAsync("api/User", content);

        //assert
        Assert.Equal(400, (int)result.StatusCode);
    }

How normally create the unit test to check the DataAnnotation validation? Or how right check this validation?


Solution

  • using System.ComponentModel.DataAnnotations;
    /*other using*/
    
    [Fact]
    public void UserValidationError()
    {
        //Arrange
        BaseUserDTO userDTO = new BaseUserDTO
        {
           FirstName = "222A@@@",
           LastName = "Test",
           Email = "[email protected]",
           PhoneNumber = "(111)111-1111",
           Role = 0,
           Password = "1234567A",
           RetypePassword = "1234567A"
        };
    
        //ACT
        var lstErrors = ValidateModel(userDTO);
    
        //ASSERT
        Assert.IsTrue(lstErrors.Count == 1);   
        //Or 
        Assert.IsTrue(lstErrors.Where(x => x.ErrorMessage.Contains("Use only Latin characters")).Count() > 0);
    }
    
    //http://stackoverflow.com/questions/2167811/unit-testing-asp-net-dataannotations-validation
            private IList<ValidationResult> ValidateModel(object model)
            {
                var validationResults = new List<ValidationResult>();
                var ctx = new ValidationContext(model, null, null);
                Validator.TryValidateObject(model, ctx, validationResults, true);
                return validationResults;
            }
    
    

    More details in Microsoft Site : https://learn.microsoft.com/en-us/aspnet/web-api/overview/testing-and-debugging/unit-testing-controllers-in-web-api