Pergunta

Há um mês terminei de ler o livro "Art of Unit Testing" e hoje finalmente tive tempo de começar a usar o Rhino Mocks com testes unitários, um serviço que envia/recebe mensagens para dispositivos (UDP) e salva/carrega dados do banco de dados.
Claro que quero isolar o banco de dados e a comunicação UDP.

Por exemplo para acesso a banco de dados, temos algumas classes com métodos estáticos, vamos chamá-las:

  • ÁreaADBAcess
  • ÁreaBDBAcesso
  • ÁreaCDBAcesso

Essas classes possuíam métodos estáticos que executavam o acesso ao banco de dados.
Para poder fazer um stub deles, tornei seus métodos públicos virtuais.

Então comecei a refatorar o código para poder substituir a instância dessas classes no código.
Depois de tentar coisas diferentes, acabei com uma aula de fábrica que parece tornar as coisas muito fáceis.

public class ObjectFactory
{
    private static Dictionary<Type, object> Instances = new Dictionary<Type, object>();

    public static T GetInstance<T>() where T : new()
    {
        if(Instances.ContainsKey(typeof(T)))
            return (T)Instances[typeof(T)];

        return new T();
    }

    public static void SetInstance<T>(object obj)
    {
        Instances[typeof(T)] = obj;
    }
}

Então, no código, posso usar

private AreaADBAccess DBAccess = ObjectFactory.GetInstance<AreaADBAccess>();

E no método de teste eu faço algo como

AreaADBAccess dbAccess = mocks.Stub<AreaADBAccess>();
using (mocks.Record())
{
...
}
ObjectFactory.SetInstance<AreaADBAccess>(dbAccess);
//Invoke the test method
...

Esta é uma primeira solução e percebo que pode ser feita de uma forma melhor.
Agora você pode comentar e me indicar as melhores práticas?
Você também pode me explicar por que eu gostaria de ter uma interface em vez de definir os métodos como virtuais?Parece inútil repetir os cabeçalhos dos métodos em 2 lugares.
Obrigado!

Foi útil?

Solução

Provavelmente você poderia fazer uso de containers IoC como Windsor, StructureMap ou Ninject, o que tornaria sua vida muito mais fácil, e na verdade eles também funcionam como "fábrica" ​​que você criou manualmente, mas são muito mais poderosos.

Também existem contêineres de automocking que criarão automaticamente dependências simuladas para suas classes, para que você possa salvar linhas adicionais de código e tornar seu teste menos frágil.

Quanto à questão da necessidade de interface em vez de classes, trata-se basicamente do Princípio de Inversão de Dependência, que afirma que módulos de nível superior (classes) não devem depender de módulos de nível inferior (classes), ambos devem depender de abstrações.Interfaces são essas abstrações.Sugiro que você dê uma olhada nos princípios S.O.L.I.D que tornarão sua vida muito mais fácil, pelo menos eles fizeram comigo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top