2012-02-19 13 views
6

Después de leer esto: How do I mock an open used in a with statement (using the Mock framework in Python)?Python Mock - Burlándose varios abierta

soy capaz de burlarse de la función abierta en Python usando:

with patch(open_name, create=True) as mock_open: 
    mock_open.return_value = MagicMock(spec=file) 
    m_file = mock_open.return_value.__enter__.return_value 
    m_file.read.return_value = 'text1' 

    diffman = Diffman() 
    diffman.diff(path1, path2) 

funciona bien cuando mi método probado utilizaba un estado de cuenta abierta. Aquí está mi método probado:

def diff(self, a, b): 
    with open(a, 'r') as old: 
     with open(b, 'r') as new: 
      oldtext = old.read() 
      newtext = new.read() 

Los valores de oldtext y newtext son los mismos ('text1' aquí).

Me gustaría tener 'text1' para el texto antiguo y 'text2' para el nuevo texto.

¿Cómo puedo hacer esto?

Respuesta

5

Aquí hay una manera rápida de obtener lo que desea. Es un poco engañoso porque los dos objetos de archivo en el método bajo prueba son el mismo objeto y solo estamos cambiando el valor de retorno de la lectura después de cada lectura. Puede usar la misma técnica en varias capas si desea que los objetos de archivo sean diferentes, pero será bastante desordenado y puede ocultar el propósito de la prueba innecesariamente.

Reemplazar esta línea:

 
    m_file.read.return_value = 'text1' 

con:

 
    reads = ['text1', 'text2'] 
    m_file.read.side_effect = lambda: reads.pop(0) 
3

Tal vez una buena solución posible es sólo para escribir el código de una manera que mejor se presta a la fácil probarlo. En el caso de 'diff', parece bastante fácil (sin tener mucho otro contexto, sin duda) tener diff tomar como argumentos objetos de archivo ya abiertos. Es probable que sea un cambio bastante pequeño en el código, y hace que las pruebas sean muy sencillas, ya que puede proporcionar fácilmente objetos de archivo simulados a diff() cuando lo prueba, en lugar de intentar saltar aros burlándose de dos instancias de la misma función integrada como un administrador de contexto llamado dentro de ... sí mismo ... o algo ;-)

import StringIO 

diff(a, b): 
    oldtext = a.read() 
    newtext = b.read() 

def test_diff(): 
    a = StringIO.StringIO('text1') 
    b = StringIO.StringIO('text2') 

    res = diff(a, b) 
    <some assertion here> 

¿Eso funcionaría para su caso?