.NET

1 dez, 2015

ASP .NET MVC – Injeção de dependência e repositório Mock – Parte 02

Publicidade

No artigo de hoje, eu vou mostrar como podemos usar o container Ninject para realizar a injeção de dependência em uma aplicação ASP .NET MVC 5 e criar um repositório Mock usando o Moq.

Na primeira parte do artigo, criamos a solução, referenciamos o Ninject e o MOQ, configuramos o container Ninject  e criamos o nosso model Produto e o nosso repositório IProdutoRepositorio.

Vamos agora criar o repositório Mock, o controlador e a view para exibir uma lista de produtos em nossa aplicação MVC usando o repositório mock.

Na figura abaixo, podemos visualizar o nosso projeto e a implementação da interface IProdutoRepositorio.cs que fizemos na primeira parte do artigo.

mock-1

Recursos usados:

Criando o repositório Mock

Abra o VS 2013 Community e clique em Open Project.

A seguir, selecione o projeto Mvc_Ninject_Moq criado na primeira parte deste artigo.

Como já definimos uma interface para o nosso repositório, podemos implementar o mecanismo de persistência vinculando-o ao nosso banco de dados. Antes de fazer isso, vamos criar uma implementação do repositório mock para a interface IProdutoRepositorio.

Vamos definir uma implementação mock vinculando-a à interface IProdutoRepositorio no método AddBindings da classe NinjectDependencyResolver que está na pasta infraestrutura do nosso projeto.

A seguir, temos o código da classe NinjectDependencyResolver onde as linhas em azul representam o código que incluímos para implementar o repositório.

Incluímos a referência ao Moq e a ao nosso Model e incluímos o código no método AddBindings:

using System;
using System.Collections.Generic;
using Ninject;
using System.Web.Mvc;
<span style="color: #0000ff;">using Moq;</span>
<span style="color: #0000ff;">using Mvc_Ninject_Moq.Models;</span>

namespace Mvc_Ninject_Moq.Infraestrutura
{
    public class NinjectDependencyResolver : IDependencyResolver
    {
        private IKernel kernel;
        public NinjectDependencyResolver(IKernel kernelParam)
        {
            kernel = kernelParam;
            AddBindings();
        }
        public object GetService(Type serviceType)
        {
            return kernel.TryGet(serviceType);
        }
        public IEnumerable&lt;object&gt; GetServices(Type serviceType)
        {
            return kernel.GetAll(serviceType);
        }
        private void AddBindings()
        {
            <span style="color: #0000ff;">Mock&lt;IProdutoRepositorio&gt; mock = new Mock&lt;IProdutoRepositorio&gt;();</span>

<span style="color: #0000ff;">            mock.Setup(m =&gt; m.Produtos).Returns(new List&lt;Produto&gt; </span>
<span style="color: #0000ff;">            {</span>
<span style="color: #0000ff;">                new Produto { Nome = "Teclado sem fio", Preco = 130 },</span>
<span style="color: #0000ff;">                new Produto { Nome = "Mouse Otico", Preco = 40 },</span>
<span style="color: #0000ff;">                new Produto { Nome = "Microfone", Preco = 15 },</span>
<span style="color: #0000ff;">                new Produto { Nome = "Pen Drive 8 GB", Preco = 59 },</span>
<span style="color: #0000ff;">                new Produto { Nome = "Fones de Ouvido", Preco = 19 }</span>
<span style="color: #0000ff;">            });</span>

<span style="color: #0000ff;">            kernel.Bind&lt;IProdutoRepositorio&gt;().ToConstant(mock.Object);</span>
       }
    }
}

O que fizemos aqui vai permitir que o Ninject retorne o mesmo objeto mock sempre que uma requisição para a implementação da interface IProdutoRepositorio for feita; foi por isso que usamos o método ToConstant para definir o escopo do Ninject:

kernel.Bind<IProdutoRepositorio>().ToConstant(mock.Object);

Assim, ao invés de criar uma nova instância da implementação do objeto a cada vez o Ninject sempre responder a requisição para a interface IProdutoRepositorio usando o mesmo objeto mock. VER COM RINA ESSA FRASE

Exibindo uma lista de produtos

Vamos criar um controlador e um método Action para pode exibir detalhes dos produtos no repositório e vamos usar o repositório mock.

Clique com o botão direito sobre a pasta Controllers do projeto MVC e selecione Add -> Controller.

Selecione o Scaffold – MVC 5 Controller – Empty e clique no botão Add.

mock-2

Informe o nome ProdutoController para o controlador e clique no botão Add.

mock-3

A seguir, remova o método Action Index criado por padrão e inclua um construtor no controlador declarando uma dependência para com a interface IProdutoRepositorio.

Fazendo assim, forçamos o Ninject a injetar a dependência para o repositório produto quando ele instanciar a classe ProdutoController.

Para poder exibir os produtos, crie um método Action chamado ListaProdutos() que irá renderizar a view:

using System.Web.Mvc;
using Mvc_Ninject_Moq.Models;

namespace Mvc_Ninject_Moq.Controllers
{
    public class ProdutoController : Controller
    {
        private IProdutoRepositorio repositorio;

        public ProdutoController(IProdutoRepositorio produtoRepositorio)
        {
            this.repositorio = produtoRepositorio;
        }

        public ViewResult ListaProdutos()
        {
            return View(repositorio.Produtos);
        }
    }
}

Note que estamos chamando o método View sem especificar um nome para view. Fazendo assim, o framework irá renderizar a view default para o método Action. Passar uma lista de objetos para o método View fornece ao framework dados com os quais ele pode popular objeto Model em uma view fortemente tipada.

Agora vamos incluir uma view default para o método Action ListaProdutos().

Clique com o botão direito no método ListaProdutos() do controlador ProdutoController e selecione Add View.

Defina o nome da view como ListaProdutos, selecione o template Empty e o Model Class Produto conforme mostra a figura abaixo e clique no botão Add.

mock-4

Será criado o arquivo ListaProduto.cshtml na pasta Views/Produto.

Vamos abrir esse arquivo e ajustar o código conforme mostrado abaixo:

@using Mvc_Ninject_Moq.Models
@model IEnumerable<Produto>

@{
    ViewBag.Title = "Produtos";
}

<h2>Lista de Produtos</h2>

@foreach (var p in Model)
{
    <div>
        <h3>@p.Nome</h3>
        @p.Descricao
        <h4>@p.Preco.ToString("c")</h4>
    </div>
}

Alteramos o código gerado por padrão no qual definimos o model como sendo do tipo IEnumerable<Produto>, pois é esse o tipo que o controlador irá obter do repositório e passar para a view.

Exibimos o preço usando a formatação ToString(“c”) que irá renderizar os valores numéricos como moeda de acordo com as configurações locais.

Vamos agora fazer alguns pequenos ajustes no arquivo _layout.cshtml na pasta Views/Shared e finalmente, antes de executar o projeto, vamos alterar a roda definida no arquivo RouteConfig.cs na pasta App_Start.

Abra o arquivo RouteConfig.cs e altere a rota conforme mostra o código abaixo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace Mvc_Ninject_Moq
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Produto", action = "ListaProdutos", id = UrlParameter.Optional }
            );
        }
    }
}

Agora podemos executar o projeto e iremos obter a nossa lista de produtos usando o Ninject e um repositório mock.

mock-5

Podemos melhorar a apresentação usando o BootStrap, mas deixo isso como uma tarefa para você.

Pegue o projeto completo aqui: Mvc_Ninject_Moq_2.zip.