unittest unit test mock python unit-testing mocking python-mock

unit - Python se burla de mĂșltiples valores de retorno



python unittest (1)

Estoy usando pitons mock.patch y me gustaría cambiar el valor de retorno para cada llamada. Aquí está la advertencia: la función que se está reparando no tiene entradas, por lo que no puedo cambiar el valor de retorno en función de la entrada.

Aquí está mi código de referencia.

def get_boolean_response(): response = io.prompt(''y/n'').lower() while response not in (''y'', ''n'', ''yes'', ''no''): io.echo(''Not a valid input. Try again'']) response = io.prompt(''y/n'').lower() return response in (''y'', ''yes'')

Mi código de prueba:

@mock.patch(''io'') def test_get_boolean_response(self, mock_io): #setup mock_io.prompt.return_value = [''x'',''y''] result = operations.get_boolean_response() #test self.assertTrue(result) self.assertEqual(mock_io.prompt.call_count, 2)

io.prompt es solo una versión independiente de la plataforma (python 2 y 3) de "entrada". Entonces, en última instancia, estoy tratando de burlar la entrada de los usuarios. He intentado usar una lista para el valor de retorno, pero eso no funciona.

Puedes ver que si el valor de retorno es inválido, obtendré un bucle infinito aquí. Entonces necesito una forma de cambiar eventualmente el valor de retorno, para que mi prueba realmente termine.

(Otra posible forma de responder esta pregunta podría ser explicar cómo podría imitar la entrada del usuario en una prueba unitaria)

No es un duplicado de esta pregunta, principalmente porque no tengo la capacidad de variar las entradas.

Uno de los comentarios de la Respuesta sobre esta pregunta está en la misma línea, pero no se ha proporcionado ninguna respuesta / comentario.


Puede asignar un iterable a side_effect , y el simulacro devolverá el siguiente valor en la secuencia cada vez que se llame:

>>> from unittest.mock import Mock >>> m = Mock() >>> m.side_effect = [''foo'', ''bar'', ''baz''] >>> m() ''foo'' >>> m() ''bar'' >>> m() ''baz''

Citando la documentación de Mock() :

Si side_effect es iterable, cada llamada al simulacro devolverá el siguiente valor de iterable.

Como un aparte, la response is not ''y'' or ''n'' or ''yes'' or ''no'' la prueba response is not ''y'' or ''n'' or ''yes'' or ''no'' no funcionará; usted está preguntando si la expresión (response is not ''y'') es verdadera, o ''y'' es verdadera (siempre es el caso, una cadena no vacía siempre es verdadera), etc. Las diversas expresiones a cada lado or operadores son independiente . Ver ¿Cómo pruebo una variable contra múltiples valores?

Tampoco debes usar is probar contra una cadena. El intérprete de CPython puede reutilizar objetos de cadena bajo ciertas circunstancias , pero este no es el comportamiento con el que debe contar.

Como tal, usa:

response not in (''y'', ''n'', ''yes'', ''no'')

en lugar; esto utilizará pruebas de igualdad ( == ) para determinar si la response referencia a una cadena con los mismos contenidos (valor).

Lo mismo se aplica a la response == ''y'' or ''yes'' ; use la response in (''y'', ''yes'') lugar.