RSS Feed

Asp.Net Mvc regular expression attribute Testing–DateTime validation problem

 

Context

When developing simple validation logic in Asp.Net Mvc you can use the built in validators. One of them is the RegularExpression Validator. I had a simple scenario with a property of  DateTime type called StartDate. Validation format (yyyy-mm-dd). It should be a simple task , but details are always messy.

I created a simple pattern and tested it with various examples in one of the Regex Editors.

 [RegularExpression(@”^(19|20)\d\d([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$”)]
 public DateTime StartDate { get; set; }
 

To check if this solution works , two unit tests were created. First implementation of tests used the Regex class , but then I found out that you can use  Attribute classes inside your code. I changed tests and used the RegularExpressionAttribute class inside test. Those tests are better because , with Regex our , we are checking if regex pattern is correct. With Attribute class used inside the test , we are testing actual scenario that is happening inside our app .

Here are the tests.

    [TestFixture]
    class CalendarEventRegExpTests
    {
        private string regex = @”^(19|20)(\d\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$”;

        [Test]
        public void Should_match()
        {
            var dateTime = “2011-10-1”;
            var attribute = new RegularExpressionAttribute(regex);
            Assert.IsTrue(attribute.IsValid(dateTime));
        }

SUCCESS

        [Test]
        public void Should_not_match()
        {
            var dateTime = “01-10-2001”;
            var attribute = new RegularExpressionAttribute(regex);
            Assert.IsFalse(attribute.IsValid(dateTime));
        }

    }

SUCCESS
 

Yey green light, They passed so it’s working ! I tested the app and … validation was always incorrect . First thought , my pattern is incorrect. But , it is working inside RegEx Editor so I it has to be correct.

Problem

It seems that when DateTime object is passed to the RegExpAttribute , something weird is happening and validation fails. I have simulated this scenario with simple test.

        [Test]
        public void Should_match()
        {
            var dateTime = new DateTime(2011,11,10);
            var attribute = new RegularExpressionAttribute(regex);
            Assert.IsTrue(attribute.IsValid(dateTime));
        }

FAIL

 

Maybe it’s the problem with the type of the object. This test converts DateTime object to string fail.

        [Test]
        public void Should_match()
        {
            var dateTime = new DateTime(2011,10,10);
            var attribute = new RegularExpressionAttribute(regex);
            Assert.IsTrue(attribute.IsValid(dateTime.ToString()));
        }

FAIL 

 

Then I realized that .ToString() , method by default creates string including the hh-mm-ss. In my scenario those parameters were initialized with zeros My simple regex pattern wont match this string. Correctly formatted string passes the Test.

        [Test]
        public void Should_match()
        {
            var dateTime = new DateTime(2011,10,10);
            var attribute = new RegularExpressionAttribute(regex);
            Assert.IsTrue(attribute.IsValid(dateTime.ToString(“yyyy-MM-dd”)));
        }

SUCCESS
 

It’s time to look inside the RegularExpressionAttribute.  Let me “Reflect” or “DotPeek”  that for you.

Here is the code inside the class.

    public override bool IsValid(object value)
    {
      this.SetupRegex();
     string input = Convert.ToString(value, (IFormatProvider) CultureInfo.CurrentCulture);
      if (string.IsNullOrEmpty(input))
      {
        return true;
      }
      else
      {
        Match match = this.Regex.Match(input);
        if (match.Success && match.Index == 0)
          return match.Length == input.Length;
        else
          return false;
      }
    }

The Highlighted part is the problem. .IsValid() method uses default.ToString(). DateTime is parsed to the string with hh-mm-ss and that’s the root of the problem.

Solution

There is a simple solution to this problem. You just need to attach DisplayFormat.

DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = “{0:yyyy-MM-dd}”)]

 

Lessons Learned

– “green light” in test doesn’t mean that your code is working .

– create tests on “real” data

– try simulate environment and context as much as possible. To many assumptions and your test isn’t testing real scenario. In my case , I  used the string inside test when my app used DateTime object.


Faking Controller User.Identity with Rhino Mocks and MvcContrib. Unit Tests in Asp.Net Mvc

Some of the actions that we are writing in Asp.Net MVC contains logic which uses data from the User context eg. user authentication or user name. Controller base class contains User property which is the instance of  IPrincipal with two important properties.

User.Identity.Name
User.Identity.IsAuthenticated

The IPrincipal is taken from the HttpContext

    public IPrincipal User
    {
      get
      {
        if (this.HttpContext != null)
          return this.HttpContext.User;
        else
          return (IPrincipal) null;
      }
    }

So if your action is using the User  property directly (you can always wrap this property inside a class that implements mockable Interface ) there is a problem with unit testing. In a isolated enviroment like test case , Controller doesn’t have the HttpContext. It is an external dependency.

HttpContext is retrieved from the ControllerContext

    public HttpContextBase HttpContext
    {
      get
      {
        if (this.ControllerContext != null)
          return this.ControllerContext.HttpContext;
        else
          return (HttpContextBase) null;
      }
    }

In order to fake the User property First we need to create a fake  ControllerContext. To create it we need  HttpContext  which also needs HttpRequest.  User is created from IPrincipal and IIdentity , with those classes we can create a Stub inside the HttpContext.

Yep , It’s quite complicated. Fortunately MvcContrib Library helps a little by providing classes that are faking IIdentity and IPrincipal

If you want to create a fake user you just need to write

var user = new FakePrincipal(new FakeIdentity(userName),null);

When creating FakeIdentity userName parametr is really important. If you want ,not authenticated user , pass Empty String as a parameter

var user = new FakePrincipal(new FakeIdentity(String.Empty), null);

 

Yey , it’s the end ! Check out this simple graph.

image

 

 

 

 

 

 

 

 

 

 

Using this information , I have implemented simple TestHelper with methods to generate Fake ControlleContext with faked User.

Code:

    public static class TestHelper
    {
        public static ControllerContext MockControllerContext(Controller controller)
        {
            var httpContext = MockRepository.GenerateMock<HttpContextBase>();
            var httpRequest = MockRepository.GenerateMock<HttpRequestBase>();
            httpContext.Stub(x => x.Request).Return(httpRequest);
            return new ControllerContext(httpContext,new RouteData(),controller);
        }

        public static ControllerContext WithAuthenticatedUser(this ControllerContext context, string userName)
        {
            var user = new FakePrincipal(new FakeIdentity(userName),null);
            context.HttpContext.Stub(x => x.User).Return(user);
            return new ControllerContext(context.HttpContext,new RouteData(),context.Controller);
        }

        public static ControllerContext WithNotAuthenticatedUser(this ControllerContext context)
        {
            var user = new FakePrincipal(new FakeIdentity(String.Empty), null);
            context.HttpContext.Stub(x => x.User).Return(user);
            return new ControllerContext(context.HttpContext, new RouteData(), context.Controller);
        }
}

Usage:

ProfileController.ControllerContext =
TestHelper.MockControllerContext(ProfileController).WithAuthenticatedUser(“test”);

Hope this sample helps.


Faking ModelState.IsValid–unit tests in Asp.Net Mvc

As a part of my thesis , I am creating web app in Asp.net MVC. I m using NHibernate , NUnit , RhinoMocks , WCF , Ninject , Glimpse and also Elmah . This is a quite big project with a lot of unit tests. I am treating it as a playground.

This is the the first post o  of a series about using unit tests with MVC and WCF .

Create entity action scenario in my app is simple. First there is a get action which builds View and prepares model. Then this newly created model (filled with values from the view)  is passed to action with [HttpPost] attribute. It is a good practice to if  ModelState.IsValid before performing any DB operations.

I have a lot of tests testing controllers and their action. In this case on of the tests should check behaviour of the controller when the ModelState.IsValid value is false. I have tried different approaches : trying to mock controller , trying to mock its context , inspecting code with dotPeek (cool decompiler from the JetBrains) wasn’t helpfull.  Then I realized that you can do something like this.

//Faking ModelState.IsValid = false          
  CourseController.ModelState.Add(“testError”, new ModelState());    
  CourseController.ModelState.AddModelError(“testError”, “test”);
Test:
[Test] 
 public void Post_if_model_state_invalid_then_dont_add_course_and_return_error_view()  
{      
      #region Arrange   

       //Faking ModelState.IsValid = false     
       CourseController.ModelState.Add(“testError”, new ModelState());                       CourseController.ModelState.AddModelError(“testError”, “test”);   

        using (Mock.Record())
        {   
             Expect.Call(CourseService.AddCourse(Course)).Repeat.Never();   
         } 
         #endregion    

         #region Act       
        ViewResult view;     
         using (Mock.Playback())  
          {  
              view = (ViewResult)CourseController.Create(Course);  
          } 
           #endregion   
           #region Assert   
           Assert.That(view.ViewName,Is.EqualTo(“Error”)); 
           Assert.That(view.ViewBag.Error, Is.EqualTo(elearn.Common.ErrorMessages.Course.ModelUpdateError));  

           #endregion 
       }

As you can see ,  I am modifying ModelState by injecting fake data that will result in IsValid property set to false.


FluentNHibernate–Testing

FluentNHibernate

 

FluentNhibernate framework provides easy way to define mappings in NHibernate. You don’t need to create complex xml files , instead you can use C# syntax and write the code in the “.cs” file. FluentNH generates cfg from it.

Just to show you how this is simple check this class mapping,

        public GroupModelMap()
        {
            Id(x => x.ID);
            Map(x => x.GroupName).Not.Nullable();

            //One
            References(x => x.GroupType).Not.LazyLoad();

            //Many
            HasMany(x=>x.Users);          
        }

Mapped class looks like this :

    public class GroupModel
    {
        public virtual int ID { get; private set; }
        public virtual string GroupName { get; set; }

        public virtual GroupTypeModel GroupType { get; set; }
        public virtual IList<ProfileModel> Users { get; set; }

    }

Every property needs to be marked as virtual and every mapped class needs ID property. It’s just simple as that. There are many options you can use. But I wont go into details in this post. If you want to try it just check the site.

In this post ,I want to show you other aspects of FluentNHibernate , that can make your life easier. FluentNH is not only about mappings anymore it provides lots of more functionalities.

 

In Memory Testing

 

When testing NHibernate layer , it is a good way to use database stored in memory. Unit tests should be isolated , so by running tests on Database Engine you break this rule.

For InMemory DB  , I  prefer the SqlLite database engine. Its quite good and FluentNH has a good “out of box” support for it. Creating InMemory DB can be a painful experience. You can encounter various problems and one of them is session management. With InMemory DB when session is closed data is deleted from memory and you don’t have access to data. In one of the projects , I have implemented my own mechanism based on the Maciej Aniserowicz samples. It worked fine, but also required a lot of testing and improving.

Fortunately for us Fluent NH provides mechanism for creating the session object leaving you problem of implementing the tests. We just need to provide the SqlLite configuration.

Something like :

                    _configuration = Fluently.Configure()
                            .Database(() => SQLiteConfiguration.Standard.InMemory().ShowSql())
                            .Mappings(x => x.FluentMappings.AddFromAssembly(typeof(ProfileModel).Assembly))
                            .BuildConfiguration();

Then you can create session and use it for tests.

var sessionSource = new SingleConnectionSessionSourceForSQLiteInMemoryTesting(configuration);

ISession session = sessionSource.CreateSession()

 

Testing Nhibernate Mappings

In unit test world with ORM layers it is good idea to test mappings. Writing your own tests can be a mundane and boring task. FluentNHibernate provides  a way to test it quite simply.

You can use the PersistenceSpecification class

                new PersistenceSpecification<ForumModel>(session, new IDEqualityComparer())
                   .CheckProperty(c => c.Name, “test”)
                   .CheckProperty(c => c.Author, “test”)
                   .CheckList<TopicModel>(c => c.Topics,
                   new List<TopicModel>()
                        {
                            new TopicModel(){ Text=“test”}
                        }
                   )
                   .VerifyTheMappings();

This class performs:

  • create ForumModel instance
  • insert this instance to DB
  • retrieve it
  • and verify if returned data is correct

Besides the session parameter this class can take Comparer class which defines the your own comparison idea .

Look at this example. In one of the projects , I am performing comparison based on the unique ID to check if Reference is correct.

    public class IDEqualityComparer : IEqualityComparer
    {
        new public bool Equals(object x, object y)
        {
            #region Comparer

            if (x == null || y == null)
            {
                return false;
            }
            if (x is IModel && y is IModel)
            {
                return ((IModel)x).ID == ((IModel)y).ID;
            }

            return x.Equals(y);
            #endregion
        }

        public int GetHashCode(object obj)
        {
            throw new NotImplementedException();
        }
    }

IModel is used here to shorten the code. It contains only ID property. Every model class implements it.

More info

http://wiki.fluentnhibernate.org/Persistence_specification_testing


NUnit Test Visual Studio Snippet

I am using NUnit framework to write Unit Tests. To simplify my work I have a simple snippet which generates test method.

[Test]
public void TestName()
{
#region Arrange
#endregion 

#region Act

Assert.Fail();

#endregion

#region Assert
#endregion
}

As you can see there are regions for different actions.

Here is a code for this snippet. If you want to use it. Just copy paste it to the xml file and name it with extensions “*.snippet”. Then in Visual Studio go to (Tools –> Code Snippet Manager) and import this file.

<CodeSnippets
xmlns=http://schemas.microsoft.com/VisualStudio/2010/CodeSnippet&#8221;>
<CodeSnippet Format=“1.0.0”>
<Header>
<Title>
NUnit Test
</Title>
</Header> 

<Snippet>
<Declarations>
<Literal>
<ID>TestName</ID>
<ToolTip>Replace with TestName.</ToolTip>
<Default>TestName</Default>
</Literal>
</Declarations>
<Code Language=“CSharp”>
<![CDATA[
[Test]
public void $TestName$()
{
#region Arrange
#endregion

#region Act

Assert.Fail();

#endregion

#region Assert
#endregion
}
]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>


Microsoft Pex – Automated Unit Testing

Microsoft Pex isa Visual Studio add in, which enables code analysis on the runtime. The great fact about it, is  the ability to generate tests automatically. I analyzed my small project with it check out the results.

 

Automated Tests

image

 

While analyzing you can watch whole process in Pex Explorer. As you can see only two of my classes passed the tests. Rest, well they are in red and that’s a bad sign. The Pex created all the tests by itself.

 

image

 

On this image you can see all the test cases generated by Pex for my Task class. Lets take a closer look at my TaskBin class and CreateFromString Method.

 

image image

 

Left image shows all the performed tests and shows, which failed or passed. On the right image, you can analyze data on which the test was run. You can clearly see on which string the test failed and, which was ok.

Values used for tests are generated based on the if statements,  assertions, and operations that can throw an exception. The code is first analyzed, and then the values are generated.

After the tests are generated you can save and store them for later use.

 

Suggestions

image

 

After the analyze process, Pex also makes suggestions with fixes to encountered problems.

 

Integration with Various Unit Test Frameworks

As a Microsoft product Pex is not only using the MsUnit tests. You can run it with :

and more.

I have used the NUnit.

 

The Future of Unit Testing ?

This is quite a nice tool. While writing tests you have to write a lot of code. Pex frees us up from this task,  at least a bit. I think that Pex will be a useful addition and will generate simplest tests. Developer will be able to focus his attention on more complex tests.

Do you think that the whole process of Unit Testing will be automated?


Testowanie jednostkowe metody prywatnej

Natknąłem się ostatnio na pewien problem.

Jak przeprowadzić test funkcji zadeklarowanej jako private wewnątrz pewnej klasy.

Rozwiązania:

1. Najbardziej oczywiste zmienić dostęp do metody na publiczny.

2. Zadeklarować metodę jako protected i dziedziczyć w innej klasie która obuduje metodę prywatną metodą publiczną [wrapper].

3.Zadeklarować funkcje jako internal i użyć Attrybutu InternalsVisibleTo. Oczywiście jeżeli kod testów trzymamy w tym samym projekcie co nasza metoda to internal już zapewnia nam dostęp do niej. Dobrą praktyką jednak jest trzymanie kodu testującego w oddzielnym Assembly.

Wszystkie te sposoby psują naszą koncepcje która z jakiegoś ważnego powodu zakładała że nasza  funkcja powinna być prywatna.

Pozostają jeszcze :

4.Użyć mechanizmu refleksji.

5. Zastanowić się czy aby na pewno powinniśmy testować metodę prywatną .Z zalożenia testy jednostkowe powinny testować interfejs naszej klasy.Testując metody prywatne narażamy sie na testowanie implementacji co przy zmianie kodu może wymusić zmianę testów.

Więcej Info