Reusable test base classes

(This applies to ASP.NET MVC and MSTest and Moq)

When writing tests for MVC controllers that inherit from the same base, you can save yourself some time by creating a test base class that is responsible for setup and teardown of your test cases:

1) Create an abstract class that takes your base controller class as a templated argument
2) Create a public method that initializes your tests. Adorn this with TestInitialize.
3) Create a public method that cleans up after your tests. Adorn this with TestCleanup.
4) Create an abstract method that initializes your controller.

Having done this, you can focus the test cases, rather than the boilerplate in your tests, simply having to override the CreateController method (step 4 above) to initialize your particular controller, given the initialized argument passed.

Example Base Class

Imports SecretCompany.Web.Controllers
Imports Moq

Namespace ControllerTests

  Public MustInherit Class ControllerTestBase(Of TController As BaseController)
    Protected RepositoryMock As Mock(Of ISecretRepository)
    Protected State As State
    Protected Controller As TController

    Protected MustOverride Function CreateController(mockedRepository As ISecretRepository, fakeState As State) As TController

    '''



    ''' http://connect.microsoft.com/VisualStudio/feedback/details/555442/visual-studio-mstest-allows-testinitialize-s-to-appear-inside-of-non-testclass-s-while-mstest-exe-does-not
    '''
   
    Public Sub TestInitialize()
      RepositoryMock = New Mock(Of ISecretRepository)
      State = New State("bananas")
      Controller = CreateController(RepositoryMock.Object, State)
    End Sub

    '''



    ''' http://connect.microsoft.com/VisualStudio/feedback/details/555442/visual-studio-mstest-allows-testinitialize-s-to-appear-inside-of-non-testclass-s-while-mstest-exe-does-not
    '''
   
    Public Sub TestCleanup()
      Controller.Dispose()
    End Sub

  End Class
End Namespace

Example Test Class

Imports SecretCompany.Common.Global.Konstanter
Imports SecretCompany.Web.Controllers
Imports Moq
Imports System.Web.Mvc

Namespace ControllerTests

 
  Public Class SecretControllerTests : Inherits ControllerTestBase(Of SecretController)
    Protected Overrides Function CreateController(ByVal mockedRepository As ISecretRepository, ByVal fakeState As State) As SecretController
      Return New SecretController(mockedRepository, fakeState)
    End Function

   
    Public Sub Index_Calls_Repository_CreateViewModel()
      Const expectedId = "70CD7009-CEE3-44DD-AF69-7416DC5B522E"
      Const expectedDate = "1981-12-29 13:37"
      Const expectedCode = Codes.SecretCode1
      Controller.Index(expectedId, expectedDate)

      RepositoryMock.Verify(Sub(mock) mock.CreateViewModel(
 It.IsAny(Of SkadehandelseBaseViewModel),
 It.IsInRange(DateTime.Now.AddMinutes(-1), DateTime.Now.AddMinutes(1), Range.Exclusive),
 expectedId,
 expectedCode,
 expectedDate,
 State.Ticket()), Times.Once())
    End Sub

   
    Public Sub Index_Returns_View()
      Const expectedDate = "1981-12-29 13:37"
      Dim result = Controller.Index(It.IsAny(Of String), expectedDate)
      Dim viewResult = TryCast(result, ViewResult)
      Assert.IsNotNull(viewResult)
    End Sub
  End Class
End Namespace

Comments

Popular posts from this blog

Auto Mapper and Record Types - will they blend?

Unit testing your Azure functions - part 2: Queues and Blobs

Testing WCF services with user credentials and binary endpoints