Compartilhar via


Criação de testes de unidade para aplicativos do ASP.NET MVC (C#)

por Stephen Walther

Saiba como criar testes de unidade para ações do controlador. Neste tutorial, Stephen Walther demonstra como testar se uma ação do controlador retorna uma exibição específica, retorna um determinado conjunto de dados ou retorna um tipo diferente de resultado de ação.

O objetivo deste tutorial é demonstrar como você pode escrever testes de unidade para os controladores em seus aplicativos ASP.NET MVC. Discutimos como criar três tipos diferentes de testes de unidade. Você aprenderá a testar a exibição retornada por uma ação do controlador, como testar os Dados de Exibição retornados por uma ação do controlador e como testar se uma ação do controlador redireciona ou não você para uma segunda ação do controlador.

Criando o controlador em Teste

Vamos começar criando o controlador que pretendemos testar. O controlador, chamado ProductController, está contido na Listagem 1.

Listagem 1 – ProductController.cs

using System;
using System.Web.Mvc;

namespace Store.Controllers
{
     public class ProductController : Controller
     {
          public ActionResult Index()
          {
               // Add action logic here
               throw new NotImplementedException();
          }

          public ActionResult Details(int Id)
          {

               return View("Details");
          }
     }
}

O ProductController contém dois métodos de ação chamados Index() e Details(). Ambos os métodos de ação retornam uma exibição. Observe que a ação Details() aceita um parâmetro chamado Id.

Testando a exibição retornada por um controlador

Imagine que queremos testar se o retorna ou não o ProductController modo de exibição correto. Queremos garantir que, quando a ação ProductController.Details() for invocada, a exibição Detalhes seja retornada. A classe de teste na Listagem 2 contém um teste de unidade para testar a exibição retornada pela ação ProductController.Details() .

Listagem 2 – ProductControllerTest.cs

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Store.Controllers;

namespace StoreTests.Controllers
{
     [TestClass]
     public class ProductControllerTest
     {
          [TestMethod]
          public void TestDetailsView()
          {
               var controller = new ProductController();
               var result = controller.Details(2) as ViewResult;
               Assert.AreEqual("Details", result.ViewName);

          }
     }
}

A classe na Listagem 2 inclui um método de teste chamado TestDetailsView(). Esse método contém três linhas de código. A primeira linha de código cria uma nova instância da ProductController classe . A segunda linha de código invoca o método de ação do Details() controlador. Por fim, a última linha de código verifica se a exibição retornada pela ação Details() é ou não a exibição Detalhes.

A ViewResult.ViewName propriedade representa o nome da exibição retornada por um controlador. Um grande aviso sobre como testar essa propriedade. Há duas maneiras pelas quais um controlador pode retornar uma exibição. Um controlador pode retornar explicitamente uma exibição como esta:

public ActionResult Details(int Id)
{
     return View("Details");
}

Como alternativa, o nome da exibição pode ser inferido do nome da ação do controlador da seguinte maneira:

public ActionResult Details(int Id)
{
     return View();
}

Essa ação do controlador também retorna uma exibição chamada Details. No entanto, o nome da exibição é inferido do nome da ação. Se você quiser testar o nome da exibição, deverá retornar explicitamente o nome da exibição da ação do controlador.

Você pode executar o teste de unidade na Listagem 2 inserindo a combinação de teclado Ctrl-R, A ou clicando no botão Executar Todos os Testes na Solução (consulte a Figura 1). Se o teste for aprovado, você verá a janela Resultados do Teste na Figura 2.

Executar todos os testes na solução

Figura 01: Executar todos os testes na solução (clique para exibir a imagem em tamanho real)

Sucesso!

Figura 02: Sucesso! (Clique para exibir a imagem em tamanho real)

Testando os dados de exibição retornados por um controlador

Um controlador MVC passa dados para uma exibição usando algo chamado View Data. Por exemplo, imagine que você deseja exibir os detalhes de um produto específico ao invocar a ação ProductController Details() . Nesse caso, você pode criar uma instância de uma Product classe (definida em seu modelo) e passar a instância para a exibição Details aproveitando View Data.

O modificado ProductController na Listagem 3 inclui uma ação atualizada Details() que retorna um Produto.

Listagem 3 – ProductController.cs

using System;
using System.Web.Mvc;

namespace Store.Controllers
{
     public class ProductController : Controller
     {
          public ActionResult Index()
          {
               // Add action logic here
               throw new NotImplementedException();
          }

          public ActionResult Details(int Id)
          {
               var product = new Product(Id, "Laptop");
               return View("Details", product);
          }
     }
}

Primeiro, a ação Details() cria uma nova instância da Product classe que representa um computador laptop. Em seguida, a instância da Product classe é passada como o segundo parâmetro para o View() método .

Você pode escrever testes de unidade para testar se os dados esperados estão contidos nos dados de exibição. O teste de unidade na Listagem 4 testa se um Produto que representa ou não um computador laptop é retornado quando você chama o método de ProductController Details() ação.

Listagem 4 – ProductControllerTest.cs

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Store.Controllers;

namespace StoreTests.Controllers
{
     [TestClass]
     public class ProductControllerTest
     {

          [TestMethod]
          public void TestDetailsViewData()
          {
               var controller = new ProductController();
               var result = controller.Details(2) as ViewResult;
               var product = (Product) result.ViewData.Model;
               Assert.AreEqual("Laptop", product.Name);
          }
     }
}

Na Listagem 4, o TestDetailsView() método testa os Dados de Exibição retornados invocando o Details() método . O ViewData é exposto como uma propriedade no ViewResult retornado invocando o Details() método . A ViewData.Model propriedade contém o produto passado para a exibição. O teste simplesmente verifica se o produto contido nos Dados de Exibição tem o nome Laptop.

Testando o resultado da ação retornado por um controlador

Uma ação de controlador mais complexa pode retornar diferentes tipos de resultados de ação, dependendo dos valores dos parâmetros passados para a ação do controlador. Uma ação do controlador pode retornar uma variedade de tipos de resultados de ação, incluindo um ViewResult, RedirectToRouteResultou JsonResult.

Por exemplo, a ação modificada Details() na Listagem 5 retorna o Details modo de exibição quando você passa uma ID de produto válida para a ação. Se você passar uma ID de produto inválida , uma ID com um valor menor que 1, você será redirecionado para a ação Index() .

Listagem 5 – ProductController.cs

using System;
using System.Web.Mvc;
namespace Store.Controllers
{
     public class ProductController : Controller
     {
          public ActionResult Index()
          {
               // Add action logic here
               throw new NotImplementedException();
          }
          public ActionResult Details(int Id)
          {
               if (Id < 1)
                    return RedirectToAction("Index");
               var product = new Product(Id, "Laptop");
               return View("Details", product);

          }
     }
}

Você pode testar o comportamento da ação Details() com o teste de unidade na Listagem 6. O teste de unidade na Listagem 6 verifica se você é redirecionado para a Index exibição quando uma ID com o valor -1 é passada para o Details() método .

Listagem 6 – ProductControllerTest.cs

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Store.Controllers;
namespace StoreTests.Controllers
{
     [TestClass]
     public class ProductControllerTest
     {
          [TestMethod]
          public void TestDetailsRedirect()
          {
               var controller = new ProductController();
               var result = (RedirectToRouteResult) controller.Details(-1);
               Assert.AreEqual("Index", result.Values["action"]);

          }
     }
}

Quando você chama o RedirectToAction() método em uma ação do controlador, a ação do controlador retorna um RedirectToRouteResult. O teste verifica se o RedirectToRouteResult redirecionará o usuário para uma ação do controlador chamada Index.

Resumo

Neste tutorial, você aprendeu a criar testes de unidade para ações do controlador MVC. Primeiro, você aprendeu a verificar se a exibição correta é retornada por uma ação do controlador. Você aprendeu a usar a ViewResult.ViewName propriedade para verificar o nome de uma exibição.

Em seguida, examinamos como você pode testar o conteúdo de View Data. Você aprendeu a marcar se o produto certo foi retornado depois View Data de chamar uma ação do controlador.

Por fim, discutimos como você pode testar se diferentes tipos de resultados de ação são retornados de uma ação do controlador. Você aprendeu a testar se um controlador retorna um ViewResult ou um RedirectToRouteResult.