Pergunta

Eu estou tentando encontrar uma maneira de falsificar o resultado de um método chamado de dentro de outro método.

Eu tenho um método "LoadData" que exige um auxiliar separado para obter alguns dados e, em seguida, ele vai transformá-lo (estou interessado em testar o resultado transformado).

Então, eu tenho um código como este:

public class MyClass(){
  public void LoadData(){
    SomeProperty = Helper.GetSomeData();
 }
 public object SomeProperty {get;set;}
}

Eu quero ter um resultado conhecido a partir do método Helper.GetSomeData (). Posso usar um quadro zombando (eu tenho experiência bastante limitado com Rhino Mocks, mas estou aberto a qualquer coisa) para forçar um resultado esperado? Se sim, como?

* Edit - Sim. Como esperado Eu não podia alcançar o hack que eu queria, eu vou ter que trabalhar para fora a melhor maneira de configurar os dados

Foi útil?

Solução

Tanto quanto eu sei, você deve criar uma interface ou uma classe abstrata base para o objeto Helper. Com Rhino Mocks você pode em seguida, retornar o valor que deseja.

Como alternativa, você pode adicionar uma sobrecarga para LoadData que aceita como parâmetros os dados que você normalmente recuperar do objeto Helper. Isso pode até ser mais fácil.

Outras dicas

Você tem um problema lá. Eu não sei se isso é um cenário simplificado de seu código, mas se a classe Helper é usado dessa maneira, então o código não é testável. Primeiro, a classe Helper é usado diretamente, de modo que você não pode substituí-lo com um mock . Em segundo lugar, você está chamando um método estático. Eu não sei sobre C #, mas em Java você não pode substituir métodos estáticos .

Você vai ter que fazer alguma refatoração para ser capaz de injetar um objeto fictício com um método fictício GetSomeData ().

Nesta versão simplificada de seu código é difícil de lhe dar uma resposta direta. Você tem algumas opções:

  • Criar uma interface para a classe Helper e fornecer uma maneira para que o cliente para injetar a implementação Helper para a classe MyClass. Mas se Helper é apenas realmente uma classe de utilitário que não faz muito sentido.
  • Criar um método protegido em MyClass chamado getSomeData e torná-lo só chamá Helper.LoadSomeData. Em seguida, substitua a chamada para Helper.LoadSomeData em LoadData por getSomeData. Agora você pode zombar o método getSomeData para retornar o valor fictício.

Cuidado com a simples criação de uma interface para a classe Helper e injetá-lo por meio de método. Isso pode expor detalhes de implementação. Por que um cliente deve fornecer uma implementação de um utilitário classe para chamar uma operação simples? Isto irá aumentar a complexidade dos clientes MyClass.

Eu recomendaria converter o que você tem em algo parecido com isto:

public class MyClass()
{
    private IHelper _helper;

    public MyClass()
    {
        //Default constructor normal code would use.
        this._helper = new Helper();
    }

    public MyClass(IHelper helper)
    {
        if(helper == null)
        {
            throw new NullException(); //I forget the exact name but you get my drift ;)
        }
        this._helper = helper;
    }

    public void LoadData()
    {
        SomeProperty = this._helper.GetSomeData();
    }
    public object SomeProperty {get;set;}
}

Agora seus suportes de classe que é conhecido como injeção de dependência. Isso permite que você injetar a implementação da classe auxiliar e assegura que sua classe só precisa depender da interface. Quando você zombar isso sei que você só criar uma simulação que usa a interface IHelper e passá-lo para o construtor e sua turma vão usar isso como se fosse a classe Helper real.

Agora, se você está preso usando a classe Helper como uma classe estática, então eu sugiro que você use um padrão de proxy / adaptador e enrole a classe estática com outra classe que suporta a interface IHelper (que você também vai precisar para criar ).

Se em algum momento você quiser levar isso um passo adiante você pode remover completamente a implementação Helper padrão da classe revisto e usar IoC (Inversão de Controle) recipientes. Se thiis é novo para você, porém, eu recomendaria concentrando-se primeiro sobre os fundamentos do porquê de tudo isso aborrecimento extra vale a pena enquanto (é IMHO).

Seus testes de unidade será parecido com este pseudo-código:

public Amazing_Mocking_Test()
{
    //Mock object setup
    MockObject mockery = new MockObject();
    IHelper myMock = (IHelper)mockery.createMockObject<IHelper>();
    mockery.On(myMock).Expect("GetSomeData").WithNoArguments().Return(Anything);

    //The actual test
    MyClass testClass = new MyClass(myMock);
    testClass.LoadData();

    //Ensure the mock had all of it's expectations met.
    mockery.VerifyExpectations();
}

Sinta-se livre para comentar, se você tiver quaisquer perguntas. (A propósito, eu não tenho idéia se tudo isso código funciona eu digitei isso no meu navegador, estou principalmente ilustrar os conceitos).

Você pode querer olhar para Typemock isolador, o que pode "fake" chamadas de método, sem forçá-lo a refatorar seu código. Eu sou um dev naquela empresa, mas a solução é viável se você gostaria de optar por não mudar seu projeto (ou não obrigados a mudá-lo para a capacidade de teste) é no www.Typemock.com

Roy blog: ISerializable.com

Sim, um quadro de zombaria é exatamente o que você está procurando. Você pode gravar / organizar como você deseja certas zombaram fora classes / stubbed para retorno.

Rhino Mocks, Typemock e Moq são todas boas opções para fazer isso.

post de Steven Walther em usar Rhino Mocks me ajudou muito quando eu comecei a jogar com Rhino Mocks.

Gostaria de tentar algo como isto:

public class MyClass(){
  public void LoadData(IHelper helper){
    SomeProperty = helper.GetSomeData();
 }

Desta forma, você pode zombar a classe auxiliar usando, por exemplo MOQ.

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