py3相对import和mock的问题之二

〇、前言

  本文主要用于记录问题,很难解决您的实际问题,见谅!

  主要介绍博主在mock的时候,一些写法问题导致的bug。技术有限,如果理解错了,欢迎留言,我会及时修改。

  本文问题核心:在python3 相对路径import的情况下,mock对应的模块,导致对应模块内其他模块导入错误。

一、问题描述

测试用例结构:

 

a.py:

# -*- coding: utf-8 -*-

import jiliguala

def afunc():
    print("this func a")

b.py:

# -*- coding: utf-8 -*-

from . import a
def bfunc():
    a.afunc()
    print("this func b")

core.py:

# -*- coding: utf-8 -*-

import unittest
import unittest.mock as mock

def test_post(x):
    print("do test http: ", x)

@mock.patch.dict("sys.modules", {
    "test.a": mock.Mock(),
})
class TestCore(unittest.TestCase):
    @mock.patch("a.afunc")
    def test1(self, test_post):
        import test.b as b
        b.bfunc()
        test_post.side_effect = test_post
        b.bfunc()

    @mock.patch("c.cpost")
    def test2(self, test_post):
        import test.c as c
        c.cfunc()
        test_post.side_effect = test_post
        c.cHttp()

  简单介绍一下,a文件是非py服务(用了一些莫名其妙的模块),b依赖于a,因此我在测试b中的代码需要将a进行隔离。

  在core代码中用装饰器的方式,将a模块隔离(from . import a这种写法,在sys.modules中就是test.a的形式),然后重写a.afunc的代码。

  好,看代码逻辑,貌似没什么问题。

结果:

   我把整个a模块都mock了,怎么还会导入a里面的模块?

  写一个空的测试类,看看有没有mock

 

结果:

 

  成功mock进去了……

  问题猜测:估计是我神奇的写法有问题。

  没错!如果直接mock那个神奇的模块的话,一点问题没有,但是如果确实有这么一个模块,用到了很多其他py命令行无法调用的模块的话,还是这种写法更好一点。

二、问题的根本原因

  这种写法的原理是在sys.modules中加入Mock实例,使得和原来的模块隔离的。

  而python的import有个问题:

    from a import  b。用这个写法的话,会先初始化模块a,然后在a模块中初始化模块b。

测试代码:

from test import d
import sys
import test

print(sys.modules)
print(dir(test))

结果:

  如图,发生问题的逻辑是:from import的时候,系统环境有对应路径,再import test的时候,会对其中的d进行初始化,导致d里面的东西也会跟着初始化。

  所以发生了上面这一幕,我明明把d都给mock了,但是d里面的import还是被执行了。

 

三、解决方法

  对于这种方式,解决方法就是不用from import 或者 直接mock那个奇怪的模块。

  主要还是这种写法的问题

 

四、总结

  还是直接mock不用的模块比较好,这方面需要注意写法。

  这篇文章在我眼里是不合格的文章,因为博主也看不懂,而且各种问题也没表述清楚……就当做是问题记录吧

posted @ 2019-12-24 17:49  二律背反GG  阅读(384)  评论(0编辑  收藏  举报