After checking at least 20 stackoverflow posts, I decided I'd share my problem here, maybe somebody can help me out.
It's quite simple, I am trying to mock a Database (to connect to another DB in the test), so I use unittest.mock.patch
self.mocks = [
"api.database.database.db",
"api.utils.checker.Checker.check_db_reachability"
]
self.mocks = [patch(mocked_func, return_value=self.db) for mocked_func in self.mocks]
After running (Console Output I printed after starting the mocks) the db import does not get mocked, however the class method I mocked the same way, got changed into a magic mock, if called.
dbtest_1 | DEBUG:test.postgres.test_crud:Changed DB:
dbtest_1 | DEBUG:test.postgres.test_crud:<databases.core.Database object at 0x7f7465e6c040>
dbtest_1 | DEBUG:test.postgres.test_crud:Changed Checker:
dbtest_1 | DEBUG:test.postgres.test_crud:<MagicMock name='check_db_reachability' id='140137474713264'>
Does somebody know what I'm doing wrong? The expected output would be, that the databases.core.Database object also gets mocked.
Found the answer myself - sharing it here, might help people who face the same out.
The problem was:
I was importing a variable / function from another module (file), which wasn't contained in a class or something similar
The problem was, I was patching the wrong location (the location where the object was defined (e.g. db = Database()) - however: You have to patch the location, where the object / variable is being imported!
Read more about the topic here: https://docs.python.org/3/library/unittest.mock.html#where-to-patch
I hope I can save you some time, I wish I found out sooner. Peace!
Related
I'd like to dynamically create a module from a dictionary, and I'm wondering if adding an element to sys.modules is really the best way to do this. EG
context = { a: 1, b: 2 }
import types
test_context_module = types.ModuleType('TestContext', 'Module created to provide a context for tests')
test_context_module.__dict__.update(context)
import sys
sys.modules['TestContext'] = test_context_module
My immediate goal in this regard is to be able to provide a context for timing test execution:
import timeit
timeit.Timer('a + b', 'from TestContext import *')
It seems that there are other ways to do this, since the Timer constructor takes objects as well as strings. I'm still interested in learning how to do this though, since a) it has other potential applications; and b) I'm not sure exactly how to use objects with the Timer constructor; doing so may prove to be less appropriate than this approach in some circumstances.
EDITS/REVELATIONS/PHOOEYS/EUREKA:
I've realized that the example code relating to running timing tests won't actually work, because import * only works at the module level, and the context in which that statement is executed is that of a function in the testit module. In other words, the globals dictionary used when executing that code is that of __main__, since that's where I was when I wrote the code in the interactive shell. So that rationale for figuring this out is a bit botched, but it's still a valid question.
I've discovered that the code run in the first set of examples has the undesirable effect that the namespace in which the newly created module's code executes is that of the module in which it was declared, not its own module. This is like way weird, and could lead to all sorts of unexpected rattlesnakeic sketchiness. So I'm pretty sure that this is not how this sort of thing is meant to be done, if it is in fact something that the Guido doth shine upon.
The similar-but-subtly-different case of dynamically loading a module from a file that is not in python's include path is quite easily accomplished using imp.load_source('NewModuleName', 'path/to/module/module_to_load.py'). This does load the module into sys.modules. However this doesn't really answer my question, because really, what if you're running python on an embedded platform with no filesystem?
I'm battling a considerable case of information overload at the moment, so I could be mistaken, but there doesn't seem to be anything in the imp module that's capable of this.
But the question, essentially, at this point is how to set the global (ie module) context for an object. Maybe I should ask that more specifically? And at a larger scope, how to get Python to do this while shoehorning objects into a given module?
Hmm, well one thing I can tell you is that the timeit function actually executes its code using the module's global variables. So in your example, you could write
import timeit
timeit.a = 1
timeit.b = 2
timeit.Timer('a + b').timeit()
and it would work. But that doesn't address your more general problem of defining a module dynamically.
Regarding the module definition problem, it's definitely possible and I think you've stumbled on to pretty much the best way to do it. For reference, the gist of what goes on when Python imports a module is basically the following:
module = imp.new_module(name)
execfile(file, module.__dict__)
That's kind of the same thing you do, except that you load the contents of the module from an existing dictionary instead of a file. (I don't know of any difference between types.ModuleType and imp.new_module other than the docstring, so you can probably use them interchangeably) What you're doing is somewhat akin to writing your own importer, and when you do that, you can certainly expect to mess with sys.modules.
As an aside, even if your import * thing was legal within a function, you might still have problems because oddly enough, the statement you pass to the Timer doesn't seem to recognize its own local variables. I invoked a bit of Python voodoo by the name of extract_context() (it's a function I wrote) to set a and b at the local scope and ran
print timeit.Timer('print locals(); a + b', 'sys.modules["__main__"].extract_context()').timeit()
Sure enough, the printout of locals() included a and b:
{'a': 1, 'b': 2, '_timer': <built-in function time>, '_it': repeat(None, 999999), '_t0': 1277378305.3572791, '_i': None}
but it still complained NameError: global name 'a' is not defined. Weird.
I am trying to write unittests for existing code which is poorly written and I'm finding it very hard to unit test.
def pay(self):
fraud = NewFraudCheck()
result, transaction = fraud.verify_transaction()
the test I have at the moment, I am patching the NewFraudCheck class
#patch checkout.pay.NewFraudCheck
def test_pay(self, mock_fraud_check):
mock_fraud_check.verify_transaction.assert_called()
The test is failing with a ValueError, stating that verify_transaction is not returning enough values to unpack.
I have tried adding
mock_fraud_check.verify_data.return_value = (1, 1231231)
however this doesn't seemt o have any effect.
There are a few issues I'll point out, but the question is missing a few details so hopefully I can address them all in one shot:
Your syntax here is wrong: #patch checkout.pay.NewFraudCheck. It should be #patch('checkout.pay.NewFraudCheck')
There is a missing class somewhere that has the function pay(self) on it. That class lives inside a module somewhere which is important to properly mock NewFraudCheck. I'll refer to that missing module as other.
NewFraudCheck needs to be patched at the point where it's looked up. That means, in the mystery module other where there's a class that has pay(self) defined in it, there's presumably an import of from pay import NewFraudCheck. That is where NewFraudCheck is looked up, so your patch will need to look like this: #patch('checkout.other.NewFraudCheck). More info here: http://www.voidspace.org.uk/python/mock/patch.html#where-to-patch
You need to assign/use the return value of your patch, not access verify_transaction directly off of the mock. For instance, it should read like this: mock_fraud_check.return_value.verify_transaction.return_value = (1, 1231231). Notice the inclusion of return_value.
The final test I came up with looked like this and passed:
#mock.patch('checkout.other.NewFraudCheck')
def test_pay(self, mock_fraud_check):
# This is the class that lives in mystery module, 'checkout.other' and calls pay()
other_class = SomeOtherClass()
mock_fraud_check.return_value.verify_transaction.return_value = (1, 1231231)
other_class.pay()
mock_fraud_check.return_value.verify_transaction.assert_called()
I'm currently looking into myHdl to see if it's worth using or not. However, I've come across a hiccup regarding the instantiation of modules. I've got two files, one that's a module and one that's the testbench. Inside the testbench, I've instantiated the module following the example they have on the website:
http://www.myhdl.org/examples/flipflops.html
The instantiation specifically is this line: dff_inst = dff(q, d, clk)
However, I get an error when I try to run the testbench:
Exception TypeError: 'isinstance() arg 2 must be a class, type, or tuple of classes and types' in <generator object _LabelGenerator at 0x7f6070b2ea50> ignored
I assume this has something to do with the fact that I have two separate files, so my guess is that python isn't finding the dff module(since it's in a separate file). I tried adding in an import dff line, but that simply gave me a 'module' object is not callable type error, which makes sense.
Looking in the documentation, they don't have a full .py file, so I'm not sure how they're linking these testbenches with the module. They specifically mention a hierarchy system and being able to instantiate other modules, but I can't seem to get it to work.
From what I understand from documentation, it looks like they're just writing the testbench and the module in the same file. However, to my understanding, it looks like they imply you can import modules, but I can't figure out how that's done. Is there just some simple thing I'm overlooking?
After experimenting a bit, it seems like I just need to use the following command: from dff import dff,
which makes a lot of sense.
I'm not really that knowledgeable about thread-safe vs non-thread-safe operations but am wondering if a problem I'm seeing might be because of that.
In my modules directory I've created a module that has a class defined.
Then in db.py I have an _after_insert trigger like so:
db.workorder._after_insert.append(lambda s,f: workorderAfterInsert(s,f))
In my _after_insert trigger I'm instantiating the class from my module like this:
import workorder.sequencer as sequencer
workorderId = id
wo = db.workorder(workorderId)
sequencer = sequencer.Sequencer(workorder_id=workorderId, db=db)
sequencer.build_bom()
sequencer.sequence()
sequencer.save_sequenced_workorder()
db.commit()
I'm not sure how to describe it, but I'm seeing random errors popping up in the execution of sequencer.sequence(). My only thought at this point is that there are thread-safe or concurrency issues going on.
I'd really appreciate it if someone could tell me whether or not this is safe (or wise). Any input would be appreciated.
-Jim
My problem was that I had my variables defined as class variables instead of instance variables. Changed that up and now it all works.
I am trying to patch methods in my flask api but it appears that the method call is not being replaced. Does app.test_client() do something under the hood that I am missing.
For example if I run
#patch('k.stats.mstats')
def test_ps(self, mstats):
mstats.return_value = (1, 2, 3)
rv = self.app.get('/ps/')
and I run through the debugger to the point below:
#app.route('/ps/', methods=['GET'])
def ps():
import pdb
pdb.set_trace()
mstats()
and inspect mstats, I will get back the function that is unmocked.
However, if I run from k.stats import mstats from the breakpoint, I get back the mocked method that I am looking for.
How do I ensure that the mocked method gets called?
This is a pretty confusing concept, but the documentation of patch tries its best to explain it.
patch works by (temporarily) changing the object that a name points to with another one. There can be many names pointing to any individual object, so for patching to work you must ensure that you patch the name used by the system under test.
The basic principle is that you patch where an object is looked up, which is not necessarily the same place as where it is defined.
This is why you're able to observe the mocked object when you decide to inject it in; you're observing the patched reference where it's looked up at that moment.
The example does an okay job of explaining what's going on there, but I'll try to clarify.
Let's say that mstats lives in module stats. You're importing it through from stats import mstats in module use_stats.
You're going to want to mock it in use_stats, since that's its place of reference.
#patch('use_stats.mstats')
def test_stats(self, mstats):
pass