Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a function called get_account(param1,param2) in run time I need to replace this function with the function mock_get_account(param1,param2) so when the system calls get_account(param1,param2) I need the mock_get_account(param1,param2) to be called instead.

I tried this code: package.get_account=self.mock_get_account package.get_account(x,y) but still the get_account runs instead of the mock_get_account I'm new to python and I don't know if this is even possible but I have seen the lamda function and I know that function programming is possible in python. Thanks Edit: if i do the following:

package.get_account=self.mock_get_account 
package.get_account(x,y) 

then every thing is ok, meaning the mock_get_account is called, but in mu code I the following code i do a post self.client.post(url, data=data, follow=True) that triggers the package.get_account and this is not working:

package.get_account=self.mock_get_account 
 package.get_account(x,y) 
 #the folowing call will trigger the package.get_account(x,y) function in a django url        #callback
 self.client.post(url, data=data, follow=True)

meaning it calls the old function, also get_account(param1,param2) is defined in side a file, and is not a child function of a class and mock_get_account(self,param1,param2) is defined in a class Test and is called inside the Test.test_account - function

share|improve this question
1  
What you have described should work fine. Please give us the actual code and results. –  Lattyware Jul 22 '13 at 13:36
    
Can you post up some actual code? Monkey patching like this is used in a number of distributed packages, so it does work if done correctly. –  Silas Ray Jul 22 '13 at 13:37
    
if i co the following: package.get_account=self.mock_get_account package.get_account(x,y) and then run package.get_account every thing is ok, in the following code i do a post self.client.post(url, data=data, follow=True) that triggers the package.get_account and this is not working, meaning it prints the old function, also get_account(param1,param2) is defined in side a file, and is not a child function of a class and mock_get_account(self,param1,param2) is defined in a class Test and is called inside the Test.test_account - function –  user1796624 Jul 22 '13 at 13:51

2 Answers 2

This is very opinionated and does not (directly) answer your question, but hopefully solves your problem.

A better practice is to use a subclass with your mock_get_account's implementation override the parent get_account method, example below:

class A(object):

    def get_account(self):
        return 1

    def post(self):
        return self.get_account()

class B(A):

    def get_account(self):
        return 2  # your original mock_get_account implementation

a = A()
print(a.get_account())

b = B()
print(b.post())  # this .post will trigger the overridden implementation of get_account
share|improve this answer

My guess is that the code implementing self.client.post has access to get_account through an import statement that looks like from package import get_account.

from package import get_account will first load package if it hasn't been already imported. Then it will look for a name get_account in that module, and whatever object that was bound to will be bound in the importing package's namespace, also under the name get_account. Thereafter the two names refer to the same object, but they are not the same name.

So if your mocking code comes along after this point, it sets the name get_account in package to instead refer to mock_get_account. But that'll only affect code that reads get_account from package again; anything that's already imported that name specially won't be affected.

If the code behind self.client.post instead had access only to package through import package, and was calling package.get_account it would work, because it's then only the object representing the package module that has been bound in the importing module's namespace. package.get_account would be reading an attribute of that object, and so would get whatever the current value is. If the from package import get_account appeared at function local scope rather than module scope, then this would behave similarly.

If I'm correct and your code is structured this way, then it's unfortunately not really package.get_account you need to rebind to a mock, but the get_account name in the module where self.client.post comes from (as well as any other modules which may call it).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.