I've been working around the socket limitations on App Engine this morning trying to get outbound XML-RPC requests to work properly. I rigged up my unit test structure and designed the following little tests:
def test_xmlrpc_call(self): """Run XMLRPC Call""" class T(threading.Thread): def run(self): def rpc_method(x): return x server = SimpleXMLRPCServer(("localhost", 5432)) server.register_function(rpc_method) server.handle_request() # Start XMLRPC Thread T().start() time.sleep(0.25) proxy = rpc.xmlrpc_proxy(LIVE_URL) self.assertTrue(proxy.rpc_method(True))
Fairly simple. It just creates a background XMLRPC thread and calls an identity function. As long as that returns True, I consider the test passing. This exercises all of my custom urlfetch transport code.
I ran the test suite and it bombed with the following error:
ProtocolError: protocolerror for localhost:5432/RPC2: \ 500 failed to fetch http://localhost:5432/RPC2: No \ api proxy found for service "urlfetch"
I apologize for the formatting. I found this confusing as I defined a method above in an 'rpc' module named 'xmlrpc_proxy.' After about 20 minutes of digging, I discovered that if you elect to run App Engine code from the command line, then you need to manually rig up some of the Google API stubs. I must have missed that little detail.
So, in the root __init__.py of tests/ directory, I now have this:
""" Special setup is required for certain App Engine stuff, namely urlfetch proxies and data store. """ from google.appengine.api import apiproxy_stub_map from google.appengine.api import urlfetch_stub # Create a stub map so we can build App Engine mock stubs. apiproxy_stub_map.apiproxy = apiproxy_stub_map.APIProxyStubMap() # Register App Engine mock stubs. apiproxy_stub_map.apiproxy.RegisterStub( 'urlfetch', urlfetch_stub.URLFetchServiceStub())
This wires up the stubs correctly and my App Engine unit tests pass as they should.
It's going to take a while to get used to coding for App Engine.