def test_replace_injections_container_already_started(container_factory, rabbit_config): class Service(object): proxy = rpc_proxy("foo_service") container = container_factory(Service, rabbit_config) container.start() with pytest.raises(RuntimeError): replace_injections(container, "proxy")
def test_replace_non_injection(container_factory, rabbit_config): class Service(object): proxy = rpc_proxy("foo_service") @rpc def method(self): pass container = container_factory(Service, rabbit_config) # error if dependency doesn't exit with pytest.raises(DependencyNotFound): replace_injections(container, "nonexist") # error if dependency is not an injection with pytest.raises(DependencyNotFound): replace_injections(container, "method")
def test_shop_checkout_integration(runner_factory, rpc_proxy_factory): """ Simulate a checkout flow as an integration test. Requires instances of AcmeShopService, StockService and InvoiceService to be running. Explicitly replaces the rpc proxy to PaymentService so that service doesn't need to be hosted. Also replaces the event dispatcher injection on AcmeShopService and disables the timer entrypoint on StockService. Limiting the interactions of services in this way reduces the scope of the integration test and eliminates undesirable side-effects (e.g. processing events unnecessarily). """ context_data = {'user_id': 'wile_e_coyote'} shop = rpc_proxy_factory('acmeshopservice', context_data=context_data) runner = runner_factory(AcmeShopService, StockService, InvoiceService) # replace ``event_dispatcher`` and ``payment_service`` injections on # AcmeShopService with Mock injections shop_container = get_container(runner, AcmeShopService) fire_event, payment_service = replace_injections( shop_container, "fire_event", "payment_service") # restrict entrypoints on StockService stock_container = get_container(runner, StockService) restrict_entrypoints(stock_container, "check_price", "check_stock") runner.start() # add some items to the basket assert shop.add_to_basket("anvil") == "anvil" assert shop.add_to_basket("invisible_paint") == "invisible_paint" # try to buy something that's out of stock with pytest.raises(RemoteError) as exc_info: shop.add_to_basket("toothpicks") assert exc_info.value.exc_type == "ItemOutOfStock" # provide a mock response from the payment service payment_service.take_payment.return_value = "Payment complete." # checkout res = shop.checkout() total_amount = 100 + 10 assert res == total_amount # verify integration with mocked out payment service payment_service.take_payment.assert_called_once_with({ 'customer': "wile_e_coyote", 'address': "12 Long Road, High Cliffs, Utah", 'amount': total_amount, 'message': "Dear Wile E Coyote. Please pay $110 to ACME Corp." }) # verify events fired as expected assert fire_event.call_count == 3
def test_replace_injections(container_factory, rabbit_config): class Service(object): foo_proxy = rpc_proxy("foo_service") bar_proxy = rpc_proxy("bar_service") baz_proxy = rpc_proxy("baz_service") @rpc def method(self, arg): self.foo_proxy.remote_method(arg) @rpc def foo(self): return "bar" container = container_factory(Service, rabbit_config) # replace a single injection foo_proxy = replace_injections(container, "foo_proxy") # replace multiple injections replacements = replace_injections(container, "bar_proxy", "baz_proxy") assert len([x for x in replacements]) == 2 # verify that container.dependencies doesn't include an rpc_proxy anymore assert all([ not isinstance(dependency, rpc_proxy.provider_cls) for dependency in container.dependencies ]) container.start() # verify that the mock injection collects calls msg = "msg" with RpcProxy("service", rabbit_config) as service_proxy: service_proxy.method(msg) foo_proxy.remote_method.assert_called_once_with(msg)
def test_replace_injections(container_factory, rabbit_config): class Service(object): foo_proxy = rpc_proxy("foo_service") bar_proxy = rpc_proxy("bar_service") baz_proxy = rpc_proxy("baz_service") @rpc def method(self, arg): self.foo_proxy.remote_method(arg) @rpc def foo(self): return "bar" container = container_factory(Service, rabbit_config) # replace a single injection foo_proxy = replace_injections(container, "foo_proxy") # replace multiple injections replacements = replace_injections(container, "bar_proxy", "baz_proxy") assert len([x for x in replacements]) == 2 # verify that container.dependencies doesn't include an rpc_proxy anymore assert all([not isinstance(dependency, rpc_proxy.provider_cls) for dependency in container.dependencies]) container.start() # verify that the mock injection collects calls msg = "msg" with RpcProxy("service", rabbit_config) as service_proxy: service_proxy.method(msg) foo_proxy.remote_method.assert_called_once_with(msg)
def test_shop_checkout_integration(runner_factory, rpc_proxy_factory): """ Simulate a checkout flow as an integration test. Requires instances of AcmeShopService, StockService and InvoiceService to be running. Explicitly replaces the rpc proxy to PaymentService so that service doesn't need to be hosted. Also replaces the event dispatcher injection on AcmeShopService and disables the timer entrypoint on StockService. Limiting the interactions of services in this way reduces the scope of the integration test and eliminates undesirable side-effects (e.g. processing events unnecessarily). """ context_data = {'user_id': 'wile_e_coyote'} shop = rpc_proxy_factory('acmeshopservice', context_data=context_data) runner = runner_factory(AcmeShopService, StockService, InvoiceService) # replace ``event_dispatcher`` and ``payment_service`` injections on # AcmeShopService with Mock injections shop_container = get_container(runner, AcmeShopService) fire_event, payment_service = replace_injections(shop_container, "fire_event", "payment_service") # restrict entrypoints on StockService stock_container = get_container(runner, StockService) restrict_entrypoints(stock_container, "check_price", "check_stock") runner.start() # add some items to the basket assert shop.add_to_basket("anvil") == "anvil" assert shop.add_to_basket("invisible_paint") == "invisible_paint" # try to buy something that's out of stock with pytest.raises(RemoteError) as exc_info: shop.add_to_basket("toothpicks") assert exc_info.value.exc_type == "ItemOutOfStock" # provide a mock response from the payment service payment_service.take_payment.return_value = "Payment complete." # checkout res = shop.checkout() total_amount = 100 + 10 assert res == total_amount # verify integration with mocked out payment service payment_service.take_payment.assert_called_once_with({ 'customer': "wile_e_coyote", 'address': "12 Long Road, High Cliffs, Utah", 'amount': total_amount, 'message': "Dear Wile E Coyote. Please pay $110 to ACME Corp." }) # verify events fired as expected assert fire_event.call_count == 3