<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
On 24/05/2011 08:31, Yoni Tsafir wrote:
<blockquote
cite="mid:BANLkTinmbz2MVMEEU8kAeBdT6fwnRZDBjg@mail.gmail.com"
type="cite">
<div dir="ltr">Moving a discussion with Michael Foord to TIP so
everyone can contribute:
<div><br>
</div>
<div>I suggested a feature to the mock framework in which you
can mock non existing imports (useful when you are
unit-testing platform dependent code).</div>
<div><br>
</div>
<div>My solution for this was the following:</div>
<div>
<div><br>
</div>
<div><span class="Apple-style-span" style="font-family:
'courier new',monospace;">real_import = __import__</span></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"><br>
</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace">def windows_safe_import(name, globals={},
locals={}, fromlist=(), *args, **kargs):</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"> if name in ["wmi", "win32api"] or (name ==
"ctypes" and fromlist is not None and "windll" in
fromlist):</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"> return MagicMock()</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"> </font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"> else:</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"> return real_import(name, globals,
locals, fromlist, *args, **kargs)</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"><br>
</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace">@patch("__builtin__.__import__", new =
windows_safe_import)</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace">class MyTestCase(unittest.TestCase):</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"><span class="Apple-tab-span"
style="white-space: pre;"> </span>...</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"><span class="Apple-tab-span"
style="white-space: pre;"> </span># (tested module was
imported only inside the test so the problematic imports
it uses won't be imported before we mock the __import__)</font></div>
</div>
<div><font class="Apple-style-span" face="'courier new',
monospace"><br>
</font></div>
<div><font class="Apple-style-span" face="arial, helvetica,
sans-serif">Michael suggested 2 alternatives:</font></div>
<div>
<div><font class="Apple-style-span" face="'courier new',
monospace">1.</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"> import sys</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"> sys.modules['wmi'] = MagicMock()</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"><br>
</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace">2. </font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"> @patch.dict('sys.modules', {'wmi':
MagicMock()})</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"><br>
</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace">Then "import wmi" will find your mock. </font><span
class="Apple-style-span" style="font-family: 'courier
new',monospace;">I'm very wary of overriding __import__
even in tests.</span></div>
<meta http-equiv="content-type" content="text/html;
charset=ISO-8859-1">
</div>
<div><font class="Apple-style-span" face="'courier new',
monospace"><br>
</font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace">
<meta http-equiv="content-type" content="text/html;
charset=ISO-8859-1">
<span class="Apple-style-span" style="font-family:
arial,helvetica,sans-serif;">Well, just wanted to update
that #1 works well, but #2 causes something weird:</span></font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"><span class="Apple-style-span"
style="font-family: arial,helvetica,sans-serif;">On PyDev
I can run the tests fine, but when I try running them with
nosetests, nose doesn't recognize any tests. If I comment
out the @patch.dict line, everything works fine.</span></font></div>
<div><font class="Apple-style-span" face="'courier new',
monospace"><span class="Apple-style-span"
style="font-family: arial,helvetica,sans-serif;">Tried to
debug it a bit but no luck...</span></font></div>
</div>
</blockquote>
<br>
Note that one fix *may* be (if you're using Python 2.5 or more
recent) to use patch.dict as a context manager so that it is called
inside the test instead of at test import time:<br>
<br>
def test_something():<br>
with patch.dict('sys.modules', {'wmi': MagicMock()}):<br>
...<br>
<br>
All the best,<br>
<br>
Michael<br>
<br>
<blockquote
cite="mid:BANLkTinmbz2MVMEEU8kAeBdT6fwnRZDBjg@mail.gmail.com"
type="cite">
<div dir="ltr">
<div>
<font class="Apple-style-span" face="'courier new', monospace"><span
class="Apple-style-span" style="font-family:
arial,helvetica,sans-serif;">Any ideas?</span></font></div>
</div>
<pre wrap="">
<fieldset class="mimeAttachmentHeader"></fieldset>
_______________________________________________
testing-in-python mailing list
<a class="moz-txt-link-abbreviated" href="mailto:testing-in-python@lists.idyll.org">testing-in-python@lists.idyll.org</a>
<a class="moz-txt-link-freetext" href="http://lists.idyll.org/listinfo/testing-in-python">http://lists.idyll.org/listinfo/testing-in-python</a>
</pre>
</blockquote>
<br>
<br>
<pre class="moz-signature" cols="72">--
<a class="moz-txt-link-freetext" href="http://www.voidspace.org.uk/">http://www.voidspace.org.uk/</a>
May you do good and not evil
May you find forgiveness for yourself and forgive others
May you share freely, never taking more than you give.
-- the sqlite blessing <a class="moz-txt-link-freetext" href="http://www.sqlite.org/different.html">http://www.sqlite.org/different.html</a>
</pre>
</body>
</html>