with - python unit test mocking example




Wie verschachtelte Funktionen? (3)

Die spöttische Bibliothek, die ich benutze, ist ... gespielt.

Ich stieß auf dieses Problem mit "verschachtelten verschachtelten Funktionen", als ich versuchte, Testfälle für eine Funktion zu schreiben (Legacy-Code).

Diese Funktion verwendete eine sehr komplexe geschachtelte Funktion mit starken Abhängigkeiten von anderen Modulen.

Ich frage mich, ob es möglich ist, verschachtelte Funktionen mit mock .


Eine Möglichkeit besteht darin, Ihre Funktion so zu ändern, dass sie optional die anzurufende Funktion annimmt, zB wenn Sie

def fn_to_test():
  def inner_fn():
    return 1
  return inner_fn() + 3

Ändere es zu:

def fn_to_test( inner_fn = null )
  def inner_fn_orig():
    return 1
  if inner_fn==null:
    inner_fn = inner_fn_orig
  return fn() + 3

Dann erhalten "echte" Anwendungen die richtige innere Funktion, und in Ihren Tests können Sie Ihre eigenen bereitstellen.

fn_to_test() # calls the real inner function
def my_inner_fn():
  return 3
fn_to_test( inner_fn=my_inner_fn ) # calls the new version

Sie könnten dies auch tun:

def fn_to_test():
  def inner_fn_orign():
    return 1
  inner_fn = inner_fn_orig
  try:
    inner_fn = fn_to_test.inner_fn
  excecpt AttributeError:
    pass
  return inner_fn() + 3

Auf diese Weise definieren Sie einfach die Überschreibung:

fn_to_test() # calls the real inner function
def my_inner_fn():
  return 3
fn_to_test.inner_fn = my_inner_fn
fn_to_test() # calls the new version

Versuchen Sie eine verschachtelte Funktion durch ein Mock-Objekt zu ersetzen? Wenn ja, ist das ziemlich einfach, egal wie kompliziert die Funktion ist. Sie können eine MagicMock verwenden , um so ziemlich jedes Python-Objekt zu ersetzen.

Wenn Sie eine Funktion simulieren müssen, die etwas zurückgibt, können Sie einfach den Parameter MagicMock return_value . Es würde ungefähr so ​​aussehen:

>>> super_nested_mock = mock.MagicMock()
>>> super_nested_mock.return_value = 42
>>> super_nested_mock()
42

Wenn Sie jedoch versuchen, ein anderes super_nested zu testen, das Ihre super_nested Funktion irgendwo im Inneren super_nested , und Sie es nachahmen möchten, müssen Sie ein Patch verwenden . In der Scheinbibliothek sieht es etwa so aus:

with patch('super_nested') as super_nested_mock:
    super_nested_mock.return_value = "A good value to test with"
    assert my_function_that_calls_super_nested(5) == 20

Hier wird alles in dem super_nested Block, der normalerweise stattdessen super_nested aufrufen würde, super_nested super_nested_mock und nur den von Ihnen festgelegten Wert zurückgeben.

Es gibt einige Subtilität, was genau Sie in den Patch-Aufruf eingeben müssen. Hauptsächlich möchten Sie das Objekt patchen, wenn das Modul, das Sie testen, es sehen würde. Weitere Informationen finden Sie unter " Wo zu patchen ".






closures