pytest:单元测试错误对象没有属性'assert_called_once_with
pytest: unittest error object has no attribute 'assert_called_once_with
我在 pytest 中编写单元测试并在 assert_called_once_with 上出错。
我厌倦了使用与 pytest 文档中所示相同的方式,但似乎我遗漏了一些东西。
# Class which I am trying to mock. (./src/Trading.py)
class BaseTrade:
def __init__(self, name):
self.name = name
class Trade(BaseTrade):
def __init__ (self, name):
BaseTrade.__init__(self, name)
def get_balance(self, value):
# do calculation and return some value
# for demo purpose hard-coding it
return value * 10
#unit test (./unitest/test_test.py
import mock
import unittest
import sys
sys.path.append("../src")
import Trading
class TestTradeClass(unittest.TestCase):
@classmethod
def setUpClass(self):
self.expected_balance = 100
@classmethod
def tearDownClass(self):
pass
def test_trade(self):
with mock.patch.object(Trading.Trade, 'get_balance', new = lambda self, x: (x * 10) ) as mock_method:
obj = Trading.Trade("AAPL")
value = obj.get_balance(10)
assert value == 100
mock_method.assert_called_once_with(100)
Error on mock_method.assert_called_once_with(100)
AttributeError: 'function' object has no attribute 'assert_called_once_with'
很难分辨,但如果 Trading.Trade.get_method()
实际上是一个原始函数而不是方法 - 您可能需要 unittest.mock.create_autospec()
这些有帮助吗?
不清楚 Trading.Trade
是什么。
如果碰巧 Trading
是一个 class,里面有一个 self.trade = Trade(...)
,那么您的问题就会大不相同。然后,您需要更深入地修补 Trade.get_method
。您可能希望从 class Trading
使用它的同一模块导入 Trade
(例如 from .trading import Trading, Trade
)- not 来自 Trade
声明自 - 然后 修补 Trade.get_method
.
我现在相信你想要side_effect
。这怎么样?一个文件,假设 test.py
:
#!/usr/bin/env python
import unittest
import mock
class BaseTrade:
def __init__(self, name):
self.name = name
class Trade(BaseTrade):
def __init__(self, name):
BaseTrade.__init__(self, name)
def get_balance(self, value):
# do calculation and return some value
# for demo purpose hard-coding it
return value * 10
class TestTradeClass(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.expected_balance = 100
def test_trade(self):
# Without mock
obj = Trade("AAPL")
value = obj.get_balance(10)
assert value == 100
# With Trade.get_balance param patched
with mock.patch.object(
Trade, 'get_balance', side_effect=lambda value: value * 11
) as mock_method:
obj = Trade("AAPL")
value = obj.get_balance(10)
assert value == 110
mock_method.assert_called_once_with(10)
if __name__ == "__main__":
unittest.main()
chmod +x test.py
./test.py
输出:
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
解释:
- 使用
side_effect
代替new
- 合并为一个文件更方便
- 删除
Trading.Trade
@classmethod
使用 cls
而不是 self
.
mock_method.assert_called_once_with(10)
,因为 side_effect
关心通过 obj.get_balance(10)
传递的值并存在以改变输出。
近一点?如果不是,您能否说明您要模拟的内容?
我在 pytest 中编写单元测试并在 assert_called_once_with 上出错。 我厌倦了使用与 pytest 文档中所示相同的方式,但似乎我遗漏了一些东西。
# Class which I am trying to mock. (./src/Trading.py)
class BaseTrade:
def __init__(self, name):
self.name = name
class Trade(BaseTrade):
def __init__ (self, name):
BaseTrade.__init__(self, name)
def get_balance(self, value):
# do calculation and return some value
# for demo purpose hard-coding it
return value * 10
#unit test (./unitest/test_test.py
import mock
import unittest
import sys
sys.path.append("../src")
import Trading
class TestTradeClass(unittest.TestCase):
@classmethod
def setUpClass(self):
self.expected_balance = 100
@classmethod
def tearDownClass(self):
pass
def test_trade(self):
with mock.patch.object(Trading.Trade, 'get_balance', new = lambda self, x: (x * 10) ) as mock_method:
obj = Trading.Trade("AAPL")
value = obj.get_balance(10)
assert value == 100
mock_method.assert_called_once_with(100)
Error on mock_method.assert_called_once_with(100)
AttributeError: 'function' object has no attribute 'assert_called_once_with'
很难分辨,但如果 Trading.Trade.get_method()
实际上是一个原始函数而不是方法 - 您可能需要 unittest.mock.create_autospec()
这些有帮助吗?
不清楚 Trading.Trade
是什么。
如果碰巧 Trading
是一个 class,里面有一个 self.trade = Trade(...)
,那么您的问题就会大不相同。然后,您需要更深入地修补 Trade.get_method
。您可能希望从 class Trading
使用它的同一模块导入 Trade
(例如 from .trading import Trading, Trade
)- not 来自 Trade
声明自 - 然后 修补 Trade.get_method
.
我现在相信你想要side_effect
。这怎么样?一个文件,假设 test.py
:
#!/usr/bin/env python
import unittest
import mock
class BaseTrade:
def __init__(self, name):
self.name = name
class Trade(BaseTrade):
def __init__(self, name):
BaseTrade.__init__(self, name)
def get_balance(self, value):
# do calculation and return some value
# for demo purpose hard-coding it
return value * 10
class TestTradeClass(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.expected_balance = 100
def test_trade(self):
# Without mock
obj = Trade("AAPL")
value = obj.get_balance(10)
assert value == 100
# With Trade.get_balance param patched
with mock.patch.object(
Trade, 'get_balance', side_effect=lambda value: value * 11
) as mock_method:
obj = Trade("AAPL")
value = obj.get_balance(10)
assert value == 110
mock_method.assert_called_once_with(10)
if __name__ == "__main__":
unittest.main()
chmod +x test.py
./test.py
输出:
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
解释:
- 使用
side_effect
代替new
- 合并为一个文件更方便
- 删除
Trading.Trade
@classmethod
使用cls
而不是self
.mock_method.assert_called_once_with(10)
,因为side_effect
关心通过obj.get_balance(10)
传递的值并存在以改变输出。
近一点?如果不是,您能否说明您要模拟的内容?