diff --git a/agithub.py b/agithub.py index 51e7df1..a165ba6 100644 --- a/agithub.py +++ b/agithub.py @@ -152,7 +152,8 @@ class Client(object): def __init__(self, username=None, password=None, token=None, - connection_properties=None + connection_properties=None, + httpClient = http.client ): # Set up connection properties @@ -171,6 +172,11 @@ def __init__(self, username=None, self.username = username self.auth_header = self.hash_pass(password) + # This argument is only used by the testing harness + if httpClient is None: + raise Exception("Invalid provider for http.CLIENT Injected") + self.httpClient = httpClient + def setConnectionProperties(self, props): ''' Initialize the connection properties. This must be called @@ -271,9 +277,9 @@ def hash_pass(self, password): def get_connection(self): if self.prop.secure_http: - conn = http.client.HTTPSConnection(self.prop.api_url) + conn = self.httpClient.HTTPSConnection(self.prop.api_url) elif self.auth_header is None: - conn = http.client.HTTPConnection(self.prop.api_url) + conn = self.httpClient.HTTPConnection(self.prop.api_url) else: raise ConnectionError( 'Refusing to authenticate over non-secure (HTTP) connection.') diff --git a/agithub_test.py b/agithub_test.py index fb7ce46..544c941 100755 --- a/agithub_test.py +++ b/agithub_test.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import agithub import mock +import mock.http.client import unittest class TestGithubObjectCreation(unittest.TestCase): @@ -62,5 +63,15 @@ def test_callMethodTest(self): , "params" : { "url" : "/path" } }) +class TestClient(unittest.TestCase): + def newClient(self, *args, **params): + return agithub.Client(*args, httpClient = mock.http.client, **params) + + def test_anonymousClient(self): + client = self.newClient() + + def test_passwordClient(self): + client = self.newClient(username="user", password="freepass") + if __name__ == '__main__': unittest.main() diff --git a/mock.py b/mock/__init__.py similarity index 100% rename from mock.py rename to mock/__init__.py diff --git a/mock/http/__init__.py b/mock/http/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mock/http/client.py b/mock/http/client.py new file mode 100644 index 0000000..758fafe --- /dev/null +++ b/mock/http/client.py @@ -0,0 +1,65 @@ +# Mock module for http.client + +class MethodCallRecorder(object): + method_calls = [] + + def recordMethodCall(self, methodName, args, params): + self.method_calls.append(MethodCall(methodName, args, params)) + + class MethodCall(object): + __slots__ = "method args params".split() + + def __init__(self, methodName, args, params): + self.method = methodName + self.args = args + self.params = params + + def __str__(self): + return { + "method": self.method, + "args" : self.args, + "parms" : self.parms + }.__str__() + + +class HTTPConnection(MethodCallRecorder): + connType = "HTTP" + def __init__(self, *args, **params): + self.recordMethodCall("__init__", args, params) + + def request(self, *args, **parms): + self.recordMethodCall("request", args, params) + + def getresponse(self, *args, **parms): + self.recordMethodCall("getresponse", args, params) + return Response() + + def close(self, *args, **parms): + recordMethodCall("close", args, params) + + +class HTTPSConnection(HTTPConnection): + connType = "HTTPS" + + +class Response(MethodCallRecorder): + status = "status" + + # headers and body should be overridden by test code + # if that should be tested + headers = { + "content-type": "text/plain" + } + body = "body text" + + def getheader(self, *args, **params): + self.recordMethodCall("getheader", args, params) + return headers[args[0].lower()] + + def getheaders(self, *args, **params): + self.recordMethodCall("getheaders", args, params) + return headers + + def read(self, *args, **params): + self.recordMethodCall("read", args, params) + return self.body