0

apologized to post bit similar question here. i am bit familiar with asp.net mvc but very new in unit testing. do not think that i know lot just see my reputation in stackoverflow.

i like to know how to write unit test code for IsValid and IEnumerable<ModelClientValidationRule> GetClientValidationRules

here i am pasting my code including my model. so anyone help me to write unit test code for the above two function. i am new in unit testing and working with VS2013 and using VS unit testing framework.

my main problem is how to write unit test code for this function specifically IEnumerable<ModelClientValidationRule> GetClientValidationRules

so here is my full code. anyone who often work with unit test then please see and come with code and suggestion if possible. thanks

Model

public class DateValTest
    {
        [Display(Name = "Start Date")]
        [DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
        public DateTime? StartDate { get; set; }

        [Display(Name = "End Date")]
        [DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
        [DateGreaterThanAttribute(otherPropertyName = "StartDate", ErrorMessage = "End date must be greater than start date")]
        public DateTime?  EndDate { get; set; }
    }

custom validation code

public class DateGreaterThanAttribute : ValidationAttribute, IClientValidatable
    {
        public string otherPropertyName;
        public DateGreaterThanAttribute() { }
        public DateGreaterThanAttribute(string otherPropertyName, string errorMessage)
            : base(errorMessage)
        {
            this.otherPropertyName = otherPropertyName;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            ValidationResult validationResult = ValidationResult.Success;
            try
            {
                // Using reflection we can get a reference to the other date property, in this example the project start date
                var containerType = validationContext.ObjectInstance.GetType();
                var field = containerType.GetProperty(this.otherPropertyName);
                var extensionValue = field.GetValue(validationContext.ObjectInstance, null);
                if(extensionValue==null)
                {
                    //validationResult = new ValidationResult("Start Date is empty");
                    return validationResult;
                }
                var datatype = extensionValue.GetType();

                //var otherPropertyInfo = validationContext.ObjectInstance.GetType().GetProperty(this.otherPropertyName);
                if (field == null)
                    return new ValidationResult(String.Format("Unknown property: {0}.", otherPropertyName));
                // Let's check that otherProperty is of type DateTime as we expect it to be
                if ((field.PropertyType == typeof(DateTime) || (field.PropertyType.IsGenericType && field.PropertyType == typeof(Nullable<DateTime>))))
                {
                    DateTime toValidate = (DateTime)value;
                    DateTime referenceProperty = (DateTime)field.GetValue(validationContext.ObjectInstance, null);
                    // if the end date is lower than the start date, than the validationResult will be set to false and return
                    // a properly formatted error message
                    if (toValidate.CompareTo(referenceProperty) < 1)
                    {
                        validationResult = new ValidationResult(ErrorMessageString);
                    }
                }
                else
                {
                    validationResult = new ValidationResult("An error occurred while validating the property. OtherProperty is not of type DateTime");
                }
            }
            catch (Exception ex)
            {
                // Do stuff, i.e. log the exception
                // Let it go through the upper levels, something bad happened
                throw ex;
            }

            return validationResult;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
            {
                ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
                ValidationType = "isgreater",
            };
            rule.ValidationParameters.Add("otherproperty", otherPropertyName);
            yield return rule;
        }
    }
Thomas
  • 33,544
  • 126
  • 357
  • 626

1 Answers1

1

What you want to do is test that if the value of EndDate is less than the value of StartDate, then the model is invalid, i.e. that the IsValid() method will throw a ValidationException

// Test that if the end date is less than the start date its invalid
[TestMethod]
[ExpectedException(typeof(ValidationException))]
public void TestEndDateIsInvalidIfLessThanStartDate()
{
    // Initialize a model with invalid values
    DateValTest model = new DateValTest(){ StartDate = DateTime.Today, EndDate = DateTime.Today.AddDays(-1) };
    ValidationContext context = new ValidationContext(model);
    DateGreaterThanAttribute attribute = new DateGreaterThanAttribute("StartDate");
    attribute.Validate(model.EndDate, context);   
}

When you run the test, if will succeed. Conversely if you were to initialize the model using

DateValTest model = new DateValTest(){ StartDate = DateTime.Today, EndDate = DateTime.Today.AddDays(1) };

the test would fail because the model is valid.

  • Side note: There are a few issues with the code in your `IsValid()` method and I will update the answer tomorrow to point them out. –  Mar 19 '16 at 10:52
  • thanks for your reply and post. i was expecting answer for this function too `GetClientValidationRules()` but u did not show how to test this function `GetClientValidationRules()` so my Ernest request that please show how to write unit test code for this function too `GetClientValidationRules` – Thomas Mar 19 '16 at 11:11
  • What are you expecting to test for? –  Mar 19 '16 at 11:15
  • i do not know and that is why asking that we should not write any unit test code for this function GetClientValidationRules() like IsValid() ? – Thomas Mar 20 '16 at 14:54
  • shade some light for my this post http://stackoverflow.com/questions/36116699/how-to-write-unit-test-code-for-my-ado-net-based-repository-from-vs2013 – Thomas Mar 20 '16 at 17:02
  • do i need to use any mock library to test my ado.net based repository or VS own unit test would be capable to write test ? – Thomas Mar 20 '16 at 17:02
  • Q1: The purpose of the `GetClientValidationRules()` method is to generate the `data-val-*` attributes in your html that are in turn used by your scripts to add rules to the `jQuery.validator`. You cannot test your scripts, or the `jquery.validate.js` and `jquery.validate.unobtrusive.js` scripts using a `TestMethod` so there is no real point in testing it. –  Mar 20 '16 at 23:20
  • Q2: (the link) - You have far too much code in that question to wade through and I'm not even sure what you actually asking so I cant really help. –  Mar 20 '16 at 23:46
  • Q3: You need both. You use the VS Testing framework for writing the tests. But you cannot reliably test database code using the real data in your database (it can change - i.e. someone edits the data - so the results will be unpredictable) so you use a mocking framework to 'mock' your database –  Mar 20 '16 at 23:49
  • i like to know how to unit test those function when my `StudentRepository` extend abstract class instead of interface. would u show me unit testing of few function of `StudentRepository` class ? – Thomas Mar 21 '16 at 08:08
  • url as follows http://stackoverflow.com/questions/36116699/how-to-write-unit-test-code-for-my-ado-net-based-repository-from-vs2013 – Thomas Mar 21 '16 at 08:10
  • how to use these class `Validator.TryValidateProperty(model, context, validationResults); Assert.IsTrue(validationResults.Count > 0);` when doing unit test coding? please show me how to use validationResults in your posted code. thanks – Thomas Mar 21 '16 at 11:27
  • u could use try validate proprty during unit test `Validator.TryValidateProperty(model, context, validationResults); Assert.IsTrue(validationResults.Count > 0);` but u did not use it and u solve it different way......why ? – Thomas Mar 21 '16 at 11:53
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/106904/discussion-between-stephen-muecke-and-thomas). –  Mar 21 '16 at 11:54
  • @StephenMuecke i am Mou friend of Thomas. i noticed that you many time answer for his post. can you plzz see my one post http://stackoverflow.com/questions/36227236/asp-net-mvc-custom-client-side-validation-for-checkboxes-is-not-working – Mou Mar 26 '16 at 06:18
  • i search loot got no good hint like how to validate multiple checkbox when use custom data annotation. my server side validation is working but client side not working. can you see me code and tell me where i made the mistake. thanks – Mou Mar 26 '16 at 06:19