def test_pagination_for_addr_results(self): mock_req = requestMock( path=b'/addr/AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM') res = self.app.get_by_addr(mock_req, 'AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM') jsn = json.loads(res) self.assertEqual(jsn['total'], 1027) results = jsn['results'] self.assertEqual(len(results), 500) mock_req = requestMock( path=b'/addr/AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM?page=1') res = self.app.get_by_addr(mock_req, 'AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM') jsn = json.loads(res) self.assertEqual(jsn['total'], 1027) results = jsn['results'] self.assertEqual(len(results), 500) mock_req = requestMock( path=b'/addr/AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM?page=2') res = self.app.get_by_addr(mock_req, 'AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM') jsn = json.loads(res) self.assertEqual(jsn['total'], 1027) results = jsn['results'] self.assertEqual(len(results), 27)
def test_pagination_for_addr_results(self): mock_req = requestMock(path=b'/addr/AXpNr3SDfLXbPHNdqxYeHK5cYpKMHZxMZ9') res = self.app.get_by_addr(mock_req, 'AXpNr3SDfLXbPHNdqxYeHK5cYpKMHZxMZ9') jsn = json.loads(res) self.assertEqual(jsn['total'], 1007) results = jsn['results'] self.assertEqual(len(results), 500) self.assertEqual(jsn['total_pages'], 3) mock_req = requestMock(path=b'/addr/AXpNr3SDfLXbPHNdqxYeHK5cYpKMHZxMZ9?page=1') res = self.app.get_by_addr(mock_req, 'AXpNr3SDfLXbPHNdqxYeHK5cYpKMHZxMZ9') jsn = json.loads(res) self.assertEqual(jsn['total'], 1007) results = jsn['results'] self.assertEqual(len(results), 500) mock_req = requestMock(path=b'/addr/AXpNr3SDfLXbPHNdqxYeHK5cYpKMHZxMZ9?page=2') res = self.app.get_by_addr(mock_req, 'AXpNr3SDfLXbPHNdqxYeHK5cYpKMHZxMZ9') jsn = json.loads(res) self.assertEqual(jsn['total'], 1007) results = jsn['results'] self.assertEqual(len(results), 500) mock_req = requestMock(path=b'/addr/AXpNr3SDfLXbPHNdqxYeHK5cYpKMHZxMZ9?page=3') res = self.app.get_by_addr(mock_req, 'AXpNr3SDfLXbPHNdqxYeHK5cYpKMHZxMZ9') jsn = json.loads(res) self.assertEqual(jsn['total'], 1007) results = jsn['results'] self.assertEqual(len(results), 7)
def test_request_scope_successive_calls(self): callee = mock.Mock() def configure(binder): binder.bind(object, to=lambda: callee(), scope=klein.ext.injector.request ) inj = injector.Injector([configure]) app = klein.Klein() kr = KleinResource(app) klein.ext.injector.KleinInjector(app, inj) @app.route("/") @injector.inject(p1=object) def test_handler(request, p1): return "Hello" @app.route("/page2") @injector.inject(p1=object) def test_handler(request, p1): return "Hello" yield _render(kr, requestMock('/')) yield _render(kr, requestMock('/')) yield _render(kr, requestMock('/page2')) self.assertEqual(callee.call_count, 3)
def test_gzip_compression(self): req = self._gen_rpc_req( "getblock", params=[ '307ed2cf8b8935dd38c534b10dceac55fcd0f60c68bf409627f6c155f8143b31', 1 ]) body = json.dumps(req).encode("utf-8") # first validate that we get a gzip response if we accept gzip encoding mock_req = requestMock( path=b'/', method="POST", body=body, headers={'Accept-Encoding': ['deflate', 'gzip;q=1.0', '*;q=0.5']}) res = self.app.home(mock_req) GZIP_MAGIC = b'\x1f\x8b' self.assertIsInstance(res, bytes) self.assertTrue(res.startswith(GZIP_MAGIC)) # then validate that we don't get a gzip response if we don't accept gzip encoding mock_req = requestMock(path=b'/', method="POST", body=body, headers={}) res = self.app.home(mock_req) self.assertIsInstance(res, str) try: json.loads(res) valid_json = True except ValueError: valid_json = False self.assertTrue(valid_json)
def test_gzip_compression(self): req = self._gen_rpc_req( "getblock", params=[ 'a0d34f68cb7a04d625ae095fa509479ec7dcb4dc87ecd865ab059d0f8a42decf', 1 ]) body = json.dumps(req).encode("utf-8") # first validate that we get a gzip response if we accept gzip encoding mock_req = requestMock( path=b'/', method="POST", body=body, headers={'Accept-Encoding': ['deflate', 'gzip;q=1.0', '*;q=0.5']}) res = self.app.home(mock_req) GZIP_MAGIC = b'\x1f\x8b' self.assertIsInstance(res, bytes) self.assertTrue(res.startswith(GZIP_MAGIC)) # then validate that we don't get a gzip response if we don't accept gzip encoding mock_req = requestMock(path=b'/', method="POST", body=body, headers={}) res = self.app.home(mock_req) self.assertIsInstance(res, str) try: json.loads(res) valid_json = True except ValueError: valid_json = False self.assertTrue(valid_json)
def test_9_by_tx(self): mock_req = requestMock(path=b'/tx/0xa2a37fd2ab7048d70d51eaa8af2815e0e542400329b05a34274771174180a7e8') res = self.app.get_by_tx(mock_req, '0xa2a37fd2ab7048d70d51eaa8af2815e0e542400329b05a34274771174180a7e8') jsn = json.loads(res) self.assertEqual(jsn['total'], 1) results = jsn['results'] self.assertEqual(len(results), 1)
def test_request_scope_sub_calls(self): callee = mock.Mock() def configure(binder): binder.bind(object, to=lambda: callee(), scope=klein.ext.injector.request ) inj = injector.Injector([configure]) app = klein.Klein() kr = KleinResource(app) klein.ext.injector.KleinInjector(app, inj) @injector.inject(arg=object) def handler_dep_dep(arg): return True @injector.inject(arg=object, depDep=handler_dep_dep) def handler_dep(arg, depDep): return True @app.route("/") @injector.inject(p1=object, depRv=handler_dep) def test_handler(request, p1, depRv): return "Hello" yield _render(kr, requestMock('/')) self.assertEqual(callee.call_count, 1)
def test_get_by_contract(self): mock_req = requestMock(path=b'/contract/b9fbcff6e50fd381160b822207231233dd3c56c2') res = self.app.get_by_contract(mock_req, 'b9fbcff6e50fd381160b822207231233dd3c56c2') jsn = json.loads(res) self.assertEqual(jsn['total'], 1006) results = jsn['results'] self.assertEqual(len(results), 500)
def test_get_by_contract_empty(self): mock_req = requestMock(path=b'/contract/910cba960880c75072d0c625dfff459f72aae047') res = self.app.get_by_contract(mock_req, '910cba960880c75072d0c625dfff459f72aae047') jsn = json.loads(res) self.assertEqual(jsn['total'], 0) results = jsn['results'] self.assertEqual(len(results), 0)
def test_get_tokens(self): mock_req = requestMock(path=b'/tokens') res = self.app.get_tokens(mock_req) jsn = json.loads(res) self.assertEqual(jsn['total'], 5) results = jsn['results'] self.assertIsInstance(results, list)
def test_4_by_block(self): mock_req = requestMock(path=b'/block/9583') res = self.app.get_by_block(mock_req, 9583) jsn = json.loads(res) self.assertEqual(jsn['total'], 1) results = jsn['results'] self.assertEqual(len(results), 1)
def test_double_injection(self): msg1 = "Hello world from injector!" msg2 = ("hello", "word") def configure(binder): binder.bind(str, to=msg1) binder.bind(tuple, to=msg2) inj = injector.Injector([configure]) app = klein.Klein() kr = KleinResource(app) klein.ext.injector.KleinInjector(app, inj) @app.route("/") @injector.inject(p1=str, p2=tuple) def test_handler(request, p1, p2): return "-".join((p1, ) + p2) request = requestMock('/') yield _render(kr, request) self.assertEqual( request.getWrittenData(), "-".join((msg1,) + msg2) )
def test_9_by_tx(self): mock_req = requestMock(path=b'/tx/0x4c927a7f365cb842ea3576eae474a89183c9e43970a8509b23570a86cb4f5121') res = self.app.get_by_tx(mock_req, '0x4c927a7f365cb842ea3576eae474a89183c9e43970a8509b23570a86cb4f5121') jsn = json.loads(res) self.assertEqual(jsn['total'], 1) results = jsn['results'] self.assertEqual(len(results), 1)
def test_get_tokens(self): mock_req = requestMock(path=b'/tokens') res = self.app.get_tokens(mock_req) jsn = json.loads(res) self.assertEqual(jsn['total'], 364) results = jsn['results'] self.assertIsInstance(results, list)
def test_7_by_addr(self): mock_req = requestMock(path=b'/addr/AL5e5ZcqtBTKjcQ8reiePrUBMYSD88v59a') res = self.app.get_by_addr(mock_req, 'AL5e5ZcqtBTKjcQ8reiePrUBMYSD88v59a') jsn = json.loads(res) self.assertEqual(jsn['total'], 127) results = jsn['results'] self.assertEqual(len(results), 127)
def test_7_by_addr(self): mock_req = requestMock(path=b'/addr/AXpNr3SDfLXbPHNdqxYeHK5cYpKMHZxMZ9') res = self.app.get_by_addr(mock_req, 'AXpNr3SDfLXbPHNdqxYeHK5cYpKMHZxMZ9') jsn = json.loads(res) self.assertEqual(jsn['total'], 1007) results = jsn['results'] self.assertEqual(len(results), 500)
def test_valid_email(self): request = requestMock(b"/api/[email protected]") deferred = _render(KleinResource(self.app), request) self.assertEqual(self.successResultOf(deferred), None) self.assertEqual(request.code, 200) self.assertEqual(request.getWrittenData(), six.b(json.dumps("*****@*****.**")))
def test_4_by_block(self): mock_req = requestMock(path=b'/block/627529') res = self.app.get_by_block(mock_req, 627529) jsn = json.loads(res) self.assertEqual(jsn['total'], 1) results = jsn['results'] self.assertEqual(len(results), 1)
def test_html_escape(self): request = requestMock(b"/api/not-a-valid-<anything>") deferred = _render(KleinResource(self.app), request) self.assertEqual(self.successResultOf(deferred), None) self.assertEqual(request.code, 400) self.assertTrue(b"'not-a-valid-<anything>'" in request.getWrittenData())
def test_invalid_serial(self): request = requestMock(b"/api/not a valid serial") deferred = _render(KleinResource(self.app), request) self.assertEqual(self.successResultOf(deferred), None) self.assertEqual(request.code, 400) self.assertTrue(b"Invalid serial number: 'not a valid serial'." in request.getWrittenData())
def test_valid_macaddr(self): request = requestMock(b"/api/00:00:DE:CA:FB:AD") deferred = _render(KleinResource(self.app), request) self.assertEqual(self.successResultOf(deferred), None) self.assertEqual(request.code, 200) self.assertEqual(request.getWrittenData(), six.b(json.dumps("00:00:DE:CA:FB:AD")))
def test_invalid_email(self): request = requestMock(b"/api/not-a-valid-email") deferred = _render(KleinResource(self.app), request) self.assertEqual(self.successResultOf(deferred), None) self.assertEqual(request.code, 400) self.assertTrue(b"Invalid email address: 'not-a-valid-email'." in request.getWrittenData())
def test_get_by_contract_empty(self): mock_req = requestMock(path=b'/contract/a3d2f26ada9cd95861eed99e43f9aafa05630849') res = self.app.get_by_contract(mock_req, 'a3d2f26ada9cd95861eed99e43f9aafa05630849') jsn = json.loads(res) self.assertEqual(jsn['total'], 0) results = jsn['results'] self.assertEqual(len(results), 0)
def test_8_bad_addr(self): mock_req = requestMock(path=b'/addr/AcFnRrVC5emrTEkuFuRPufcuTb6KsAJ3v') res = self.app.get_by_addr(mock_req, 'AcFnRrVC5emrTEkuFuRPufcuTb6KsAJ3v') jsn = json.loads(res) self.assertEqual(jsn['total'], 0) results = jsn['results'] self.assertIsInstance(results, type(None)) self.assertIn('Could not get notifications', jsn['message'])
def test_6_block_num_too_big(self): mock_req = requestMock(path=b'/block/2060200054055066') res = self.app.get_by_block(mock_req, 2060200054055066) jsn = json.loads(res) self.assertEqual(jsn['total'], 0) results = jsn['results'] self.assertIsInstance(results, type(None)) self.assertIn('Higher than current block', jsn['message'])
def test_5_block_no_results(self): mock_req = requestMock(path=b'/block/206') res = self.app.get_by_block(mock_req, 206) jsn = json.loads(res) self.assertEqual(jsn['total'], 0) results = jsn['results'] self.assertIsInstance(results, list) self.assertEqual(len(results), 0)
def test_9_by_bad_tx(self): mock_req = requestMock(path=b'/tx/2e4168cb2d563714d3f35ff76b7efc6c7d428360c97b6b45a18b5b1a4faa40') res = self.app.get_by_tx(mock_req, b'2e4168cb2d563714d3f35ff76b7efc6c7d428360c97b6b45a18b5b1a4faa40') jsn = json.loads(res) self.assertEqual(jsn['total'], 0) results = jsn['results'] self.assertIsInstance(results, type(None)) self.assertIn('Could not get tx with hash', jsn['message'])
def test_6_block_num_too_big(self): mock_req = requestMock(path=b'/block/2060200054055066') res = self.app.get_by_block(mock_req, 2060200054055066) jsn = json.loads(res) self.assertEqual(jsn['total'], 0) results = jsn['results'] self.assertIsInstance(results, list) self.assertIn('Could not get notifications', jsn['message'])
def test_block_heigher_than_current(self): mock_req = requestMock(path=b'/block/8000000') res = self.app.get_by_block(mock_req, 800000) jsn = json.loads(res) self.assertEqual(jsn['total'], 0) results = jsn['results'] self.assertIsInstance(results, type(None)) self.assertIn('Higher than current block', jsn['message'])
def test_get_host_nonstandard_https_port(hostchecker): request = requestMock(b"/foo", host=b'example.com', port=8443, isSecure=True) request.requestHeaders.removeHeader( b'host') # force hostchecker to use transport attributes assert hostchecker.get_host(request) == 'example.com:8443'
def test_get_by_contract_empty(self): mock_req = requestMock( path=b'/contract/a3d2f26ada9cd95861eed99e43f9aafa05630849') res = self.app.get_by_contract( mock_req, 'a3d2f26ada9cd95861eed99e43f9aafa05630849') jsn = json.loads(res) self.assertEqual(jsn['total'], 0) results = jsn['results'] self.assertEqual(len(results), 0)
def test_route_token_required(self): request = requestMock(b"/", headers={b'Authorization': [str(mock.sentinel)]}) returned = self.app.execute_endpoint("token_required_endpoint", request) self.assertEqual(returned, self.userinfo) self.auth.decode_header_value.assert_called_once_with( str(mock.sentinel))
def test_7_by_addr(self): mock_req = requestMock( path=b'/addr/AL5e5ZcqtBTKjcQ8reiePrUBMYSD88v59a') res = self.app.get_by_addr(mock_req, 'AL5e5ZcqtBTKjcQ8reiePrUBMYSD88v59a') jsn = json.loads(res) self.assertEqual(jsn['total'], 127) results = jsn['results'] self.assertEqual(len(results), 127)
def test_assertResponseContentType_match(self) -> None: """ :meth:`TestCase.assertResponseContentType` does not raise when given a request with the expected response ``Content-Type`` header. """ request = requestMock(b"/") request.setHeader("content-type", "text/l33t") self.assertResponseContentType(request, "text/l33t")
def test_verification(self): extra = {"twilio-token": test_token, "twilio-receiver": test_url} s = SMSReceiver(Config(extra)) signature = generate_signature(test_url, test_form, test_token) headers = {"X-Twilio-Signature": [signature]} r = requestMock(test_path, method="POST", host=test_host, port=test_port, body=urllib.urlencode(test_form), headers=headers) r.args = test_form self.assertTrue(s.validSignature(r))
def test_7_by_addr(self): mock_req = requestMock( path=b'/addr/AcFnRrVC5emrTEkuFuRPufcuTb6KsAJ3vR') res = self.app.get_by_addr(mock_req, 'AcFnRrVC5emrTEkuFuRPufcuTb6KsAJ3vR') jsn = json.loads(res) self.assertEqual(jsn['total'], 3) results = jsn['results'] self.assertEqual(len(results), 3)
def test_assertResponseCode_match(self) -> None: """ :meth:`TestCase.assertResponseCode` does not raise when given a request with the expected response code. """ request = requestMock(b"/") request.code = 201 self.assertResponseCode(request, 201)
def test_route_token_required_with_cookie(self): request = requestMock(b"/") request.received_cookies = {b'token': mock.sentinel} returned = self.app.execute_endpoint("token_required_endpoint", request) self.assertEqual(returned, self.userinfo) self.auth.decode_token.assert_called_once_with(mock.sentinel)
def get(self, uri): """ Issue a virtual GET request to the given path that is expected to succeed synchronously, and return the generated request object and written bytes. """ request = requestMock(uri) d = _render(self.kr, request) self.successResultOf(d) return request, request.getWrittenData()
def test_get_host_nonstandard_https_port_ignoring_forwarded(): hostchecker_ = hostchecker({'USE_X_FORWARDED_HOST': False}) request = requestMock(b"/foo", host=b'example.com', port=8443, isSecure=True, headers={'X-Forwarded-Host': ['example.net']}) request.requestHeaders.removeHeader( b'host') # force hostchecker to use transport attributes assert hostchecker_.get_host(request) == 'example.com:8443'
def test_static_entity(self) -> None: """ :func:`static` returns the entity returned by the wrapped method. """ app = self.Application() request = requestMock(b"/") entity = app.root(request) self.assertIdentical(entity, app.hello)
def test_assertResponseCode_mismatch(self) -> None: """ :meth:`TestCase.assertResponseCode` raises :obj:`self.failureException` when given a request without the expected response code. """ request = requestMock(b"/") request.code = 500 self.assertRaises( self.failureException, self.assertResponseCode, request, 201 )
def test_pagination_for_addr_results(self): mock_req = requestMock(path=b'/addr/AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM') res = self.app.get_by_addr(mock_req, 'AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM') jsn = json.loads(res) self.assertEqual(jsn['total'], 1027) results = jsn['results'] self.assertEqual(len(results), 500) mock_req = requestMock(path=b'/addr/AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM?page=1') res = self.app.get_by_addr(mock_req, 'AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM') jsn = json.loads(res) self.assertEqual(jsn['total'], 1027) results = jsn['results'] self.assertEqual(len(results), 500) mock_req = requestMock(path=b'/addr/AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM?page=2') res = self.app.get_by_addr(mock_req, 'AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM') jsn = json.loads(res) self.assertEqual(jsn['total'], 1027) results = jsn['results'] self.assertEqual(len(results), 27)
def test_static_etag(self) -> None: """ :func:`static` sets an ``ETag`` header. """ app = self.Application() request = requestMock(b"/") app.root(request) etags = request.responseHeaders.getRawHeaders("etag") self.assertTrue(len(etags) == 1, etags) etag = etags[0] self.assertTrue(etag)
def test_static_cacheControl(self) -> None: """ :func:`static` sets a ``Cache-Control`` header. """ app = self.Application() request = requestMock(b"/") app.root(request) etags = request.responseHeaders.getRawHeaders("cache-control") self.assertTrue(len(etags) == 1, etags) etag = etags[0] self.assertTrue(etag)
def test_assertResponseContentType_mismatch(self) -> None: """ :meth:`TestCase.assertResponseContentType` raises :obj:`self.failureException` when given a request without the expected response ``Content-Type`` header. """ request = requestMock(b"/") request.setHeader("content-type", "text/plain") self.assertRaises( self.failureException, self.assertResponseContentType, request, "text/l33t" )
def test_gzip_compression(self): req = self._gen_rpc_req("getblock", params=['a0d34f68cb7a04d625ae095fa509479ec7dcb4dc87ecd865ab059d0f8a42decf', 1]) body = json.dumps(req).encode("utf-8") # first validate that we get a gzip response if we accept gzip encoding mock_req = requestMock(path=b'/', method="POST", body=body, headers={'Accept-Encoding': ['deflate', 'gzip;q=1.0', '*;q=0.5']}) res = self.app.home(mock_req) GZIP_MAGIC = b'\x1f\x8b' self.assertIsInstance(res, bytes) self.assertTrue(res.startswith(GZIP_MAGIC)) # then validate that we don't get a gzip response if we don't accept gzip encoding mock_req = requestMock(path=b'/', method="POST", body=body, headers={}) res = self.app.home(mock_req) self.assertIsInstance(res, str) try: json.loads(res) valid_json = True except ValueError: valid_json = False self.assertTrue(valid_json)
def test_basic_injection(self): TEST_MSG = "Hello world from injector!" def configure(binder): binder.bind(str, to=TEST_MSG) inj = injector.Injector([configure]) app = klein.Klein() klein.ext.injector.KleinInjector(app, inj) @app.route("/") @injector.inject(injectedParam=str) def test_handler(request, injectedParam): return injectedParam request = requestMock('/') kr = KleinResource(app) yield _render(kr, request) self.assertEqual(request.getWrittenData(), TEST_MSG)
def request(root_resource, method, endpoint, headers=None, body=None): """ Make a mock request to the REST interface :param method: http method :type method: ``str`` in (``GET``, ``POST``, ``PUT``, ``DELETE``) :param endpoint: Absolute path to the endpoint, minus the API version :type endpoint: ``str`` :param headers: Any headers to include :type headers: ``dict`` of ``list`` :param body: the body to include in the request :type body: ``str`` """ # handle query args, since requestMock does not (see # twisted.web.http.py:Request.requestReceived) with_query = endpoint.split(b'?', 1) if len(with_query) == 1: mock_request = requestMock(endpoint, method, headers=headers, body=body) mock_request.args = {} else: mock_request = requestMock(with_query[0], method, headers=headers, body=body) mock_request.args = parse_qs(with_query[1]) # these are used when writing the response mock_request.code = 200 mock_request.getClientIP = mock.MagicMock(spec=(), return_value='ip') mock_request.setHeader = mock.MagicMock(spec=()) # twisted request has a responseHeaders (outgoing headers) and # requestHeaders (incoming headers, set by requestMock) mock_request.responseHeaders = http.Headers() # if setHeader has been called a with unicode value, twisted will raise a # TypeError after the request has been closed and it is attemptig to write # to the network. So just fail here for testing purposes def _twisted_compat(name, value): if not isinstance(name, str) or not isinstance(value, str): raise TypeError("Can only pass-through bytes on Python 2") mock_request.responseHeaders.addRawHeader(name, value) mock_request.setHeader.side_effect = _twisted_compat def build_response(_): # build a response that offers some useful attributes of an IResponse status_code = 200 if mock_request.setResponseCode.call_args is not None: # first non-keyword arg - getting it from call_args means the non # kwargs are the first argument, not the second status_code = mock_request.setResponseCode.call_args[0][0] # if the content-type has not been set, Twisted by default sets the # content-type to be whatever is in # twisted.web.server.Request.defaultContentType, so replicate that # functionality if not (mock_request.responseHeaders.hasHeader('Content-Type') or Request.defaultContentType is None): mock_request.responseHeaders.setRawHeaders( 'Content-Type', [Request.defaultContentType]) # Annoying implementation detail: if the status code is one of the # status codes that should not have a body, twisted replaces the # write method of the request with a function that does nothing, so # no response body can every be written. This messes up the mock # request's write function (which just returns another mock). So # in this case, just return the empty string. content = '' if status_code not in http.NO_BODY_CODES: content = mock_request.getWrittenData() response = mock.MagicMock(spec=['code', 'headers'], code=status_code, headers=mock_request.responseHeaders) return ResponseWrapper(response=response, content=content, request=mock_request) return _render( getChildForRequest(root_resource, mock_request), mock_request).addCallback(build_response)
def mock_request(body): return requestMock(path=b'/', method="POST", body=body)
def test_3_index(self): mock_req = requestMock(path=b'/') res = self.app.home(mock_req) self.assertIn('endpoints', res)