首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python Mox:如何仅为某些路径伪造os.path.exists()?

Python Mox:如何仅为某些路径伪造os.path.exists()?
EN

Stack Overflow用户
提问于 2015-02-23 00:36:56
回答 1查看 569关注 0票数 0

我如何才能只对某些路径模拟exists(),而让它对任何其他路径做真实的事情呢?

例如,被测试的类将调用exists(),并在提供给它的路径上失败,因为它们不存在于运行测试的系统上。

使用Mox可以完全清除exists(),但这会导致测试失败,因为与被测类无关的调用将不会以真正的方式运行。

我想,当exists()被调用时,我可以使用WithSideEffects()来调用我自己的函数,将调用分为两个方向,但是如何访问原始的exists()

这就是我到目前为止所知道的:

代码语言:javascript
复制
def test_with_os_path_exists_partially_mocked(self):

    self.mox.StubOutWithMock(os.path, 'exists')

    def exists(path):
        if not re.match("^/test-path.*$", path):
            return call_original_exists_somehow(path)
        else:
            # /test-path should always exist
            return True

    os.path.exists(mox.Regex("^.*$")).MultipleTimes().WithSideEffects(exists)

    self.mox.ReplayAll()

    under_test.run()

    self.mox.VerifyAll()
EN

回答 1

Stack Overflow用户

发布于 2015-02-23 00:36:56

Mox内部使用"Stubout“作为实际的存根:

代码语言:javascript
复制
Mox.__init__()
    self._mock_objects = []
    self.stubs = stubout.StubOutForTesting()


Mox.StubOutWithMock()
    ...
    self.stubs.Set(obj, attr_name, stub)

Stubout将存根保存在内部集合中:

代码语言:javascript
复制
StubOutForTesting.Set():
    ...
    self.cache.append((parent, old_child, child_name))

由于中间调用的返回值被缓存在mocked方法对象中,因此必须在副作用回调中重置它。

当创建方法模拟时,它将被推送到将存储在_expected_calls_queue中。在重放模式中,预期的调用由一个MultipleTimesGroup实例表示,该实例将跟踪对_methods中引用的每个方法的调用。

因此,您可以通过导航Mox.stubs.cache来引用origial方法。

此示例将模拟通过对原始函数的调用传递exists(),如果它们不是以/test-path开头,则任何其他调用都将始终返回True

代码语言:javascript
复制
class SomeTest(unittest.TestCase):

    def setUp(self):
        self.mox = mox.Mox()

    def tearDown(self):
        self.mox.UnsetStubs()

    def test_with_os_path_exists_partially_mocked(self):

        self.mox.StubOutWithMock(os.path, 'exists')

        # local reference to Mox
        mox_ = self.mox

        # fake callback
        def exists(path):
            # reset returnvalues of previous calls
            # iterate mocked methods. the indices denote
            # the mocked object and method and should
            # have the correct values
            for method in mox_._mock_objects[0]._expected_calls_queue[0]._methods:
                method._return_value = None

            if not re.match("^/test-path.*$", path):
                # call real exists() for all paths not
                # starting with /test-path

                # lookup original method:
                # - filter by name only (simplest matching)
                # - take the 2nd value in the tupel (the function)
                orig_exists = filter(lambda x: x[2] == "exists", mox_.stubs.cache)[0][1]
                # call it
                return orig_exists(path)
            else:
                # hardcoded True for paths starting with /test-path
                return True

        # expect call with any argument, multiple times, and call above fake
        os.path.exists(mox.Regex("^.*$")).MultipleTimes().WithSideEffects(exists)

        self.mox.ReplayAll()

        # test goes here

        self.mox.VerifyAll()
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28660321

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档