Pergunta

Eu estou tentando testar uma classe que gerencia o acesso de dados no banco de dados (você sabe, CRUD, essencialmente). A biblioteca DB estamos usando acontece de ter uma API que você pegar o primeiro objeto de tabela por uma chamada estática:

function getFoo($id) {
  $MyTableRepresentation = DB_DataObject::factory("mytable");
  $MyTableRepresentation->get($id);
  ... do some stuff
  return $somedata
}

... você começa a idéia.

Estamos tentando testar este método, mas zombando as coisas DataObject para que (a) não precisa de uma conexão db real para o teste, e (b) que nem sequer precisa incluir o lib DB_DataObject para o teste.

No entanto, em PHPUnit eu não consigo obter $ this-> getMock () para definir adequadamente uma chamada estática. Eu tenho ...

        $DB_DataObject = $this->getMock('DB_DataObject', array('factory'));

... mas o teste ainda diz método desconhecido "fábrica". Eu sei que está criando o objeto, porque antes ele disse que não poderia encontrar DB_DataObject. Agora ele pode. Mas, nenhum método?

O que eu realmente quero fazer é ter dois objetos mock, uma para o objeto de tabela voltou também. Assim, não só eu preciso especificar que a fábrica é uma chamada estática, mas também que ela retorna algum outro objeto fictício especificado que eu já tenha configurado.

Eu devo mencionar como uma advertência de que eu fiz isso em SimpleTest um tempo atrás (não é possível encontrar o código) e funcionou muito bem.

O que dá?

[UPDATE]

Eu estou começando a entender que ele tem algo a ver com a espera ()

Foi útil?

Solução

Eu concordo com tanto de você que seria melhor não usar uma chamada estática. No entanto, eu acho que eu esqueci de mencionar que DB_DataObject é uma biblioteca de terceiros, ea chamada estática é sua melhores práticas para o seu uso de código, não o nosso. Há outras maneiras de usar seus objetos que envolvem a construção do objeto retornado diretamente. Ele só deixa aqueles darned include / require em qualquer arquivo de classe está usando essa classe DB_DO. Isso é péssimo, porque os testes vão quebrar (ou simplesmente não ser isolado) se você está tentando entretanto para zombar uma classe com o mesmo nome no seu teste -. Pelo menos eu acho

Outras dicas

Quando você não pode alterar a biblioteca, alterar o acesso do mesmo. Refatorar todas as chamadas para DB_DataObject :: factory () para um método de instância em seu código:

function getFoo($id) {
  $MyTableRepresentation = $this->getTable("mytable");
  $MyTableRepresentation->get($id);
  ... do some stuff
  return $somedata
}

function getTable($table) {
  return DB_DataObject::factory($table);
}

Agora você pode usar um mock parcial da classe que você está testando e ter getTable () retorna um objeto de tabela simulada.

function testMyTable() {
  $dao = $this->getMock('MyTableDao', array('getMock'));
  $table = $this->getMock('DB_DataObject', ...);
  $dao->expects($this->any())
      ->method('getTable')
      ->with('mytable')
      ->will($this->returnValue($table));
  $table->expects...
  ...test...
}

Este é um bom exemplo de uma dependência em seu código -. O projeto tornou-se impossível para injetar em um Mock em vez da classe verdadeira

Minha primeira sugestão seria tentar e refatorar o código para usar uma instância em vez de uma chamada estática.

O que está faltando (ou não?) De sua classe DB_DataObject é um setter para passar um objeto db preparado antes de chamar o método de fábrica. Dessa forma, você pode passar um mock ou um objeto db personalizado (com a mesma interface) Se a necessidade surgir.

Em sua configuração de teste:

 public function setUp() {
      $mockDb = new MockDb();
      DB_DataObject::setAdapter($mockDb);
 }

O método factory () deve retornar a instância DB zombou. Se ainda não estiver integrado em sua classe, você provavelmente terá que refatorar o método factory (), bem como para fazê-lo funcionar.

Você exigem / inclusive o arquivo de classe para DB_DataObject em seu caso de teste? Se a classe não existe antes PHPUnit tenta ridicularizar o objeto que você pode obter erros como estes.

Com extensão PHPUnit MockFunction mais runkit você também pode métodos estáticos simulados. Tenha cuidado, porque é patching macaco e, portanto, só deve ser usado em casos extremos. não substituir as boas práticas de programação.

https://github.com/tcz/phpunit-mockfunction

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