Existe alguma maneira de definir diferentes expectativas de simulação para diferentes argumentos de entrada? Por exemplo, tenho uma classe de camada de banco de dados chamada DB. Esta classe possui um método chamado "Query (string $ query)", esse método recebe uma string de consulta SQL na entrada. Posso criar simulação para esta classe (banco de dados) e definir diferentes valores de retorno para diferentes chamadas de método de consulta que dependem da string de consulta de entrada?
117
Respostas:
A biblioteca PHPUnit Mocking (por padrão) determina se uma expectativa corresponde com base unicamente no matcher passado para o
expects
parâmetro e na restrição passada paramethod
. Por causa disso, duasexpect
chamadas que diferem apenas nos argumentos passados parawith
falharão porque ambas corresponderão, mas apenas uma verificará como tendo o comportamento esperado. Veja a caixa de reprodução após o exemplo de trabalho real.Para seu problema, você precisa usar
->at()
ou->will($this->returnCallback(
conforme descrito emanother question on the subject
.Exemplo:
Reproduz:
Reproduza porque duas chamadas -> with () não funcionam:
Resulta em
fonte
$this->anything()
como um dos parâmetros para->logicalOr()
permitir que você forneça um valor padrão para outros argumentos além daquele em que você está interessado.Não é ideal para usar
at()
se você puder evitá-lo, porque como seus documentos afirmamDesde 4.1 você pode usar,
withConsecutive
por exemplo.Se você quiser fazer com que ele retorne em ligações consecutivas:
fonte
Fatal error: Call to undefined method PHPUnit_Framework_MockObject_Builder_InvocationMocker::withConsecutive()
, atualizei para 4.1 em um piscar de olhos com o Composer e está funcionando.willReturnOnConsecutiveCalls
matou.Pelo que descobri, a melhor maneira de resolver esse problema é usando a funcionalidade de mapa de valor do PHPUnit.
Exemplo da documentação do PHPUnit :
Este teste é aprovado. Como você pode ver:
Pelo que posso dizer, esse recurso foi introduzido no PHPUnit 3.6 , então é "antigo" o suficiente para que possa ser usado com segurança em praticamente qualquer ambiente de desenvolvimento ou teste e com qualquer ferramenta de integração contínua.
fonte
Parece Mockery ( https://github.com/padraic/mockery ) suporta isso. No meu caso, quero verificar se 2 índices são criados em um banco de dados:
Zombaria, funciona:
PHPUnit, falha:
Zombaria também tem uma sintaxe IMHO melhor. Parece ser um pouco mais lento do que a capacidade de mocking embutida do PHPUnits, mas YMMV.
fonte
Introdução
Ok, vejo que existe uma solução fornecida para Mockery, então como eu não gosto de Mockery, vou dar a você uma alternativa de Profecia, mas eu sugiro que você primeiro leia sobre a diferença entre Mockery e Prophecy.
Resumindo : "A profecia usa uma abordagem chamada vinculação de mensagens - significa que o comportamento do método não muda com o tempo, mas sim pelo outro método."
Código problemático do mundo real para cobrir
Solução PhpUnit Prophecy
Resumo
Mais uma vez, Prophecy é mais incrível! Meu truque é alavancar a natureza de ligação de mensagens do Prophecy e, mesmo que infelizmente pareça um código de inferno javascript de retorno de chamada típico, começando com $ self = $ this; como você raramente precisa escrever testes de unidade como este, acho que é uma boa solução e é definitivamente fácil de seguir, depurar, pois realmente descreve a execução do programa.
BTW: há uma segunda alternativa, mas requer a alteração do código que estamos testando. Poderíamos envolver os criadores de problemas e movê-los para uma classe separada:
pode ser embrulhado como:
e é isso mas como não queria criar outra turma para isso, prefiro a primeira.
fonte