Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python单元测试模拟-检查在正确点返回的函数_Python_Mocking_Unit Testing - Fatal编程技术网

python单元测试模拟-检查在正确点返回的函数

python单元测试模拟-检查在正确点返回的函数,python,mocking,unit-testing,Python,Mocking,Unit Testing,我有一个方法如下所示: def foo(self): if not self.started: self.start() return None # do some other stuff... self.bar() return self.baz() def test1(self): thing = Thing() thing.started = False # Maybe it would make sense t

我有一个方法如下所示:

def foo(self):
    if not self.started:
        self.start()
        return None

    # do some other stuff...
    self.bar()
    return self.baz()
def test1(self):
  thing = Thing()
  thing.started = False  # Maybe it would make sense to include this
  thing.start = Mock()
  thing.bar = Mock()

  res = thing.foo()
  assert res is None
  assert thing.start.called
  assert not thing.bar.called 
我正在编写一个名为
test\u foo\u的测试调用\u start\u如果\u还没有\u已经\u启动\u,然后\u立即返回\u

如果我们调用
start
进行测试很容易:

with mock.patch.object(Thing, 'start') as mock_start:
    thing = Thing()
    thing.foo()
    self.assertTrue(mock_start.called)

但是,我如何测试函数随后立即返回呢?我想我可以模拟bar和baz,检查它们是否没有被调用,但维护起来会很痛苦。

如果没有看到更多的代码,很难知道,但我想说的是,一种技术是在
self
上使用下一个函数调用,并断言没有被调用。而且如果没有,只有在没有开始的时候才会返回,那么你就有了优势

假设
self.bar()
是即时调用,修补
bar
,然后检查它是否没有被调用,就像

assert not mock_start.calls
然而,我更喜欢使用非常短的单元测试,并对方法进行修补(如果不使用某种依赖注入),而不是使用上下文管理器。部分模拟的对象无论如何会立即丢弃,因此这样做是安全的。大概是这样的:

def foo(self):
    if not self.started:
        self.start()
        return None

    # do some other stuff...
    self.bar()
    return self.baz()
def test1(self):
  thing = Thing()
  thing.started = False  # Maybe it would make sense to include this
  thing.start = Mock()
  thing.bar = Mock()

  res = thing.foo()
  assert res is None
  assert thing.start.called
  assert not thing.bar.called 

模拟框架可以简化很多测试活动,但最终可测试性归结为代码及其质量。一般的提示是:返回有意义的值,将代码重新分解成更小的方法,允许更精确地检查调用,或者改变状态,或者返回一个值,但不能两者都返回,等等。

yeh,这与我在问题底部提到的内容是一致的。这是可以的,但是如果函数更复杂,例如,顶部可能有一个很长的if…elif块,我必须检查是否所有可能的下一个函数调用都没有被调用。我建议重新考虑你的函数。保持较小,将代码移到其他函数(例如可能的
if…elif
块)并检查对这些其他函数的调用,返回清除的内容(如果没有启动,则返回一个都不,或者其他一些东西,这会让人感到奇怪)。总是有办法的。在我的问题中,你将如何重构函数?我不能不看你的真实代码,对不起。但如果它是你正在展示的,测试它没有什么大不了的。