0

My Fake Mock Class looks like following:

class FakeResponse:
 method = None # 
 url = None # static class variables
 def __init__(self, method, url, data):#, response):
 self.status_code = 200 # always return 200 OK
 FakeResponse.method = method # 
 FakeResponse.url = url #
 @staticmethod
 def check(method, url, values):
 """ checks method and URL. 
 """
 print "url fake: ", FakeResponse.url
 assert FakeResponse.method == method
 assert FakeResponse.url == url

I have another decorator which is applicable over all the test cases:

@pytest.fixture(autouse=True)
def no_requests(monkeypatch):
 monkeypatch.setattr('haas.cli.do_put',
 lambda url,data: FakeResponse('PUT', url, data))
 monkeypatch.setattr("haas.cli.do_post",
 lambda url,data: FakeResponse('POST', url, data))
 monkeypatch.setattr("haas.cli.do_delete",
 lambda url: FakeResponse('DELETE', url, None))

I am using Py.test to test the code.

Some example test cases are:

class Test:
 #test case passes
 def test_node_connect_network(self):
 cli.node_connect_network('node-99','eth0','hammernet')
 FakeResponse.check('POST','http://abc:5000/node/node-99/nic/eth0/connect_network',
 {'network':'hammernet'})
 # test case fails
 def test_port_register(self):
 cli.port_register('1') # This make a indirect REST call to the original API
 FakeResponse.check('PUT','http://abc:5000/port/1', None)
 # test case fails
 def test_port_delete(self):
 cli.port_delete('port', 1)
 FakeResponse.check('DELETE','http://abc:5000/port/1', None) 

A sample error message which I get:

 method = 'PUT', url = 'http://abc:5000/port/1', values = None
 @staticmethod
 def check(method, url, values):
 """ checks method and URL.
 'values': if None, verifies no data was sent.
 if list of (name,value) pairs, verifies that each pair is in 'values'
 """
 print "url fake: ", FakeResponse.url
> assert FakeResponse.method == method
E assert 'POST' == 'PUT'
E - POST
E + PUT
haas/tests/unit/cli_v1.py:54: AssertionError
--------------------------------------------- Captured stdout call -------------------------------------
port_register <port>
Register a <port> on a switch
url fake: http://abc:5000/node/node-99/nic/eth0/connect_network
--------------------------------------------- Captured stderr call -------------------------------------
Wrong number of arguements. Usage: 

Whereas if I call the second test case in the following way considering the check function takes "self" argument and @staticmethod is not used then the test case works:

def test_port_register(self):
 cli.port_register('1')
 fp = FakeResponse('PUT','http://abc:5000/port/1', None) #Create a FakeResponse class instance
 fp.check('PUT','http://abc:5000/port/1', None) # Just call the check function with the same 
 arguments

Questions:

  • Are there any side effects of using monkey patching and @staticmethod
  • How is the url defined for a previous test function being used in the next function call.
  • Should'nt there be a scoping of argument to disallow the above unwanted behavior.
  • Is there a better way to monkey patch.

Sorry for the long post, I have been trying to resolve this for a week and wanted some perspective of other programmers.

user4815162342
159k22 gold badges351 silver badges419 bronze badges
asked Nov 18, 2014 at 15:34
4
  • It's not clear what you are expecting to happen here. You're explicitly using class attributes, so I don't see why you're surprised when they persist between instances: that's the whole point of class attributes. Commented Nov 18, 2014 at 15:49
  • Is there a better way to accomplish the fake test. Internally the attributes of FakeResponse class are used in another module to do some computation. Commented Nov 18, 2014 at 17:50
  • Try to debug cli.port_register('1') and check it not call a POST request after the PUT. Your code is not beautiful but it should work... but only check last call to FakeResponse() Commented Nov 19, 2014 at 8:15
  • You can try to use mock framework to build a mock request. I can try to fill an answer later by using mock framework. Commented Nov 19, 2014 at 8:20

1 Answer 1

2

The issue was not having the right signature for one of the functions. It was resolved by changing the argument passed to the MonkeyPatch function as en empty dictionary {} instead of 'None' value which is kind of specific to my code.

The reason the I was initially hitting the issue was, as the current function's call(cli.port_register) was failing when the parameters where passed to port_register itself, so it picked up the argument values from a previous state and doing the assert with the FakeResponse call.

answered Nov 21, 2014 at 15:46
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.