Skip Navigation Links
Novas Tecnologias
Ferramentas Adicionais
Ferramentas Adicionais
Testabilidade em WebForms : Fazendo Mocks de Request
Data:3/26/2013

Translate this page now :





Categories: .NET , Visual Studio , ASP.NET , Unity Test

Gostou do texto ? Vote e dê sua opinião! Pontuação atual :
Adicione aos Favoritos!
BlogBlogs Rec6 Linkk Ueba Technorati Delicious DiggIt! StumbleUpon

Veja Também



aspnetA classe Page, base para todo webform, possui propriedades Request, Response, Session, Server e Application que são frequentemente utilizadas no ASP.NET para manipularmos a comunicação, sessão e obtermos informações do servidor.

Para podermos executar testes unitários é absolutamente necessário que possamos fazer mocks dessas propriedades e desta forma rodar os testes sem a necessidade de rodar a página em um servidor.

Porém essas propriedades devolvem instâncias de tipos sealed, sem interfaces implementadas, impedindo a realização de mocks.

Para resolver esse problema surgiu no framework .NET a classe HttpContextWrapper e as classes “Base” : HttpRequestBase, HttpResponseBase e outras. Ao contrário das classes originais, essas classes “Base” são abstratar, permitindo facilmente o uso de mocks.

Devemos então re-implementar as propriedades Request, Response, Session, Server e Application de forma a retornar os novos tipos abstratos e não mais os antigos. Importante notar que não é possível fazer override, pois estaremos alterando o tipo da propriedade, então precisamos utilizar o “new”, que permite esconder uma implementação da classe pai.

Repare ainda que utilizamos “virtual” na criação das novas propriedades, pois isso as torna “mockaveis”.

Veja como fica o código :

        HttpContextWrapper cw;
        public new virtual HttpRequestBase Request
        {
            get
            {
                if (cw == null)
                {
                    cw = new HttpContextWrapper(Context);
                }
                return cw.Request;
            }
        }

        public new virtual HttpResponseBase Response
        {
            get
            {
                if (cw == null)
                {
                    cw = new HttpContextWrapper(Context);
                }
                return cw.Response;
            }
        }

        public new virtual HttpApplicationStateBase Application
        {
            get
            {
                if (cw == null)
                {
                    cw = new HttpContextWrapper(Context);
                }
                return cw.Application;
            }
        }

        public new virtual HttpSessionStateBase Session
        {
            get
            {
                if (cw == null)
                {
                    cw = new HttpContextWrapper(Context);
                }
                return cw.Session;
            }
        }

        public new virtual HttpServerUtilityBase Server
        {
            get
            {
                if (cw == null)
                {
                    cw = new HttpContextWrapper(Context);
                }
                return cw.Server;
            }
        }

Como esse código é extenso, o ideal é inserir esse código em uma classe que herde de Page e depois fazer com que todos os webforms herdem dela.

Veja um exemplo bem simples de código que depende dessa implementação para se tornar testável :

        protected void Button1_Click(object sender, EventArgs e)
        {
            Label1.Text = Request.AnonymousID;
        }

Utilizando o “Create Unit Test” do menu de contexto, geramos um novo projeto de teste para esse método, Button1_Click. Para fazer mock irei utilizar uma biblioteca chamada Moq, que podemos instalar na forma de um pacote Nuget (Manage Nuget packages permite isso).

SNAG-0017

Com o Moq instalado, podemos fazer o código do nosso método de teste. Veja como fica :

        [TestMethod()]
        public void Button1_ClickTest()
        {
            // Mock do RequestBase para controlar o anonymousID
            // Seria impossível sem o requestbase
            var rb = new Mock();
            rb.Setup<string>(x => x.AnonymousID).Returns("Teste");

            // Webform usa por default um private accessor
            var wf = new Mock();
            wf.Setup(x => x.Request).Returns(rb.Object);
            WebForm1_Accessor target = new WebForm1_Accessor(new PrivateObject(wf.Object));

            //Controlando o label
            Label lbl = new Label();
            target.Label1 = lbl;

            target.Button1_Click(null, null);

            Assert.IsTrue(lbl.Text == "Teste", "Falhou");
        }

Claro que você, na prática, irá utilizar exemplos bem mais complexos do que esse, mas o principio é o mesmo.

Importante : No VS 2012 ocorreram mudanças no sistema de testes, esse exemplo não funcionará exatamente desta forma, funcionando apenas no VS 2010. Publicarei mais sobre o assunto.



Categories: .NET , Visual Studio , ASP.NET , Unity Test


Nome :
E-mail:
Comentarios :
 
 
Os Últimos Comentários
Nenhum comentário foi realizado ainda. Seja o primeiro !
Dicas
Dica do Dia
Receba Dicas Por Email
E-mail :  
 


 (help)
Aceito receber informativos do devASPNet, informações de eventos e treinamentos

Veja Quais Informativos Você Receberá

Pesquisar Dicas
Pesquisar Artigos, Dicas e Noticias

Banco de Dados
Algumas Entrevistas
Links Importantes

Búfalo Informática, Treinamento e Consultoria
R. Alvaro Alvim, 37/920 Centro - Cinelândia - Rio de Janeiro Cep: 20031-010
Tel : (21) 2262-1368 (21) 9240-5134 E-mail : Contato@bufaloinfo.com.br