RSS Feed

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.


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>


TimeIsMoney 0.2.1 and future development

What’s New

  • 0.2.1
    • More advanced AddItemBox with option “more”.
      • three additional properties :
        • priority
        • due date
        • estimated time
    • Changed the way settings panel is displayed
    • Lots of stability fixes ….
      • fixed the problem with GlobalKeyHook and garbage collected element crash
      • various problems with list

This week i am starting unit testing. Small standalone project based on the NUnit platform with various unit tests. Idea of unit test is really simple:

  1. Make assumption about how your code should behave.
  2. Write a test to check if you are right or wrong.

I know that for some of you it looks like a waste of time but this process accelerates the development time and what’s also important it promotes good coding practices.

The next big Things which I want to start is Report Module this will be a  standalone application communicating with main software. It is responsible for various analyses of  the TODO lists. Right now I m planning to write UI inn WPF. In the beginning, I want to create simple engine.  Unit testing will be heavily used in this module.

Some major re-factorization will be necessary in the future. Isolation of the UI from the logic is really important, it’s commonly used pattern.


Next Week

  • 0.2.2
    • Ability to set up notification lists
    • Fix  priority display
    • Display estimated time and priority on the unsorted tasks lists view
    • Create NUnit testing project

  • 0.2.3
    • Ability to set up next learning and next action lists with notifications options

  • 0.2.4
    • Report Module Engine

What’s Planned?

  • 0.3.0
    • Notification mechanism based on the “IronPython”

.image

  • 0.3.5
    • More advanced report module. , statistics , daily weekly reports .
    • Progress and efficiency of time management
  • 0.5.0
    • Task trees.
    • Adding item to specific tree node

  • 0.6.0
    • Activity Tracker
      • Created from scratch or integrated with Activity Tracker Gadget
  • 0.7.0
    • Desk Notes
  • 0.8.0
    • Calendar

Far Far Away …… web application.

What i have learned this week !

The biggest enemy of the open source projects is … TIME.

Don’t love your code and be ready to throw away a good idea just because it is too complicated . Remember ….. KiSS – Keep It Simple Stupid


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