I'm writing "unittests" for my flask api. Using Flask.test_client() is easy locally. eg:
app = Flask(__name__)
client = app.test_client()
However, I want to still be able to do things such as
self.client.post('{0}/account/password'.format(self.base_path),
data=json.dumps(passwordu), headers=self.get_headers(),
content_type=self.content_type)
But I want the client to talk to a remote host.
I've seen I can use environ_override as a parameter to the client.post(...) method. To me there must be a simpler way to get a simple client that does the necessary sending of requests and decoding of responses in the same way test_client() does. However, subclassing client, still requires me to use a Flask instance.
Ok, firstly, thanks for the suggestion Anarci. Here's what I came up with.
I wouldn't call it nice OO design, but it works and is lazy.
class RemoteApiTest(AppTest, ApiTestMixin):
@classmethod
def setUpClass(cls):
super(RemoteApiTest, cls).setUpClass()
cls.kwargs = config.FLASK_CLIENT_CONFIG
cls.base_url = cls.kwargs.get('base_url')
cls.content_type = cls.kwargs.get('content_type')
cls.client = requests
cls.db = db
cls.db.create_all()
@classmethod
def tearDownClass(cls):
super(RemoteApiTest, cls).tearDownClass()
cls.db.session.remove()
cls.db.drop_all()
#cls.db.get_engine(cls.app).dispose()
@property
def base_url(self):
return self.__class__.base_url
@property
def content_type(self):
return self.__class__.content_type
def get_json(self, r):
return r.json()
@property
def headers(self):
headers = {'content-type': self.content_type}
if self.api_key:
headers.update({'X-consumer-apiKey': self.api_key})
return headers
def basic_checks(self, rv):
eq_(rv.status_code, 200)
r = rv.json()
assert rv is not None
assert r is not None
assert r.get('correlationID') is not None
return r
def setUp(self):
super(RemoteApiTest, self).setUp()
self.api_key = None
r = self.client.post('{0}/account/register'.format(self.base_url), data=json.dumps(account_register),
headers=self.headers)
j = r.json()
self.api_key = j['apiKey']
def tearDown(self):
rv = self.client.delete('{0}/account'.format(self.base_url), headers=self.headers)
super(RemoteApiTest, self).tearDown()
With that I can config the remote server etc in my same config, and I can reuse code like this:
class ApiTestMixin:
def test_account_get(self):
rv = self.client.get(self.base_url + '/account', headers=self.headers)
r = self.basic_checks(rv)
account = r.get('account')
eq_(account.get('fullName'), account_register.get('fullName'))
assert r.get('correlationID') is not None
Definitely open to criticism, but that's how I made it work,
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With