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.
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<object> GetServices(Type serviceType) { return kernel.GetAll(serviceType); } private void AddBindings() { <span style="color: #0000ff;">Mock<IProdutoRepositorio> mock = new Mock<IProdutoRepositorio>();</span> <span style="color: #0000ff;"> mock.Setup(m => m.Produtos).Returns(new List<Produto> </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<IProdutoRepositorio>().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.
Informe o nome ProdutoController para o controlador e clique no botão Add.
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.
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.
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.