Isolamento de Código SharePoint com Microsoft Fakes

Cenário do dia:

Aplicação usa SharePoint Client Object Model, recebe ClientContext, faz validações, e bingo: testes de unidade

Uma dúvida vem a mente…

Como testar uma aplicação que usa SharePoint sem SharePoint?

Microsoft Fakes

Microsoft Fakes é um framework para isolamento de código. Ele permite que você substitua partes da sua aplicação mesmo que estas não estejam disponíveis. E isso é muito útil quando se fala em testes de unidade.

Este framework possui dois pilares principais:

  1. Stubs
    Stub substitui uma classe que implementa a mesma interface. Para usá-lo é necessário projetar sua aplicação para que cada componente dependa de interfaces.
  2. Shims
    Uma Shim modifica o código compilado da sua aplicação em tempo de execução, de forma que em vez de realizar uma chamada a um método especificado, ele executa o código Shim.

 Shims podem ser usados para substituir chamadas de assemblies que não podemos modificar. Um exemplo, os Assemblies do .net

agora Vamos ao código

Nossa aplicação tem o seguinte método:

public static Web GetWebCurrent(ClientContext context)
{
   var web = context.Web;
   context.Load(web);

   // realiza validações 
   
   context.ExecuteQuery();
   return web;
}

Num rápido olhar sob o método, seu funcionamento se resume em:

  1. Resgatar uma web
  2. Realizar o load() na web
  3. Realizar validações
  4. Realizar o executeQuery()
  5. Retornar uma web

Agora precisamos testar este método porém ele se utiliza de recursos, SharePoint, que devem estar disponíveis.

Agora entra a brincadeira com o Microsoft Fakes…

Os Objetos “ClientContext” e “Web” são pertencentes a dll “Microsoft.Sharepoint.Client”.

Por conta disso vamos utilizar Shims para “fakear” estes objetos e isolar o SharePoint.

Assim temos:

[Fact]
public void Web_Not_Null()
{
   using (ShimsContext.Create())
   {
       #region Arrange
       // isola o ClientContext
       var ctx = new ShimClientContext
       {
          // isola a Web
          WebGet = () => new ShimWeb
          {
             TitleGet = () => "MockWeb"
          },
          ExecuteQuery = () => { }
       };

       // isola o ClientRuntimeContext
       var ctxRuntime = new ShimClientRuntimeContext(ctx);

       // escreve a funcionalidade do método Load()
       ctxRuntime.LoadOf1M0ExpressionOfFuncOfM0ObjectArray((a, b) => { });
       ctxRuntime.LoadQueryOf1ClientObjectCollectionOfM0(delegate { return null; });
       ctxRuntime.LoadQueryOf1IQueryableOfM0(delegate { return null; });

       #endregion
       // act
       var result = NossoCodigo.GetWebCurrent(ctx);

       // assert
       Assert.NotNull(result);
   }
}

No nosso arrange, é onde definimos as Shims de ClientContext, Web e ClientContextRuntime; substituindo os métodos e propriedades que queremos para que durante a execução do método “GetWebCurrent” estes sejam utilizados.

A mágica acontece principalmente por conta da ShimsContext.Create();
É através dela que é criada um contexto de shims e é permitido que em tempo de execução as substituições ocorram sem problemas.

Bem, por hoje é isso.
Espero que tenham gostado!

Amanhã, trarei mais assuntos abordando a criação dos fakes assemblies, redução de warnings e muito mais.