test_internal_gateway.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. from typing import cast
  2. import pytest
  3. from pydantic import Field
  4. from clean_python import Conflict
  5. from clean_python import DoesNotExist
  6. from clean_python import Filter
  7. from clean_python import Id
  8. from clean_python import InMemoryGateway
  9. from clean_python import InternalGateway
  10. from clean_python import Json
  11. from clean_python import Manage
  12. from clean_python import Repository
  13. from clean_python import RootEntity
  14. from clean_python import ValueObject
  15. # domain - other module
  16. class User(RootEntity):
  17. name: str = Field(min_length=1)
  18. class UserRepository(Repository[User]):
  19. pass
  20. # application - other module
  21. class ManageUser(Manage[User]):
  22. def __init__(self):
  23. self.repo = UserRepository(gateway=InMemoryGateway([]))
  24. async def update(self, id: Id, values: Json) -> User:
  25. if values.get("name") == "conflict":
  26. raise Conflict()
  27. return await self.repo.update(id, values)
  28. # domain - this module
  29. class UserObj(ValueObject):
  30. id: int
  31. name: str
  32. # infrastructure - this module
  33. class UserGateway(InternalGateway[User, UserObj]):
  34. def __init__(self, manage: ManageUser):
  35. self._manage = manage
  36. @property
  37. def manage(self) -> ManageUser:
  38. return self._manage
  39. def _map(self, obj: User) -> UserObj:
  40. return UserObj(id=cast(int, obj.id), name=obj.name)
  41. @pytest.fixture
  42. def internal_gateway():
  43. return UserGateway(manage=ManageUser())
  44. async def test_get_not_existing(internal_gateway: UserGateway):
  45. assert await internal_gateway.get(1) is None
  46. async def test_add(internal_gateway: UserGateway):
  47. actual = await internal_gateway.add(UserObj(id=12, name="foo"))
  48. assert actual == UserObj(id=12, name="foo")
  49. @pytest.fixture
  50. async def internal_gateway_with_record(internal_gateway):
  51. await internal_gateway.add(UserObj(id=12, name="foo"))
  52. return internal_gateway
  53. async def test_get(internal_gateway_with_record):
  54. assert await internal_gateway_with_record.get(12) == UserObj(id=12, name="foo")
  55. async def test_filter(internal_gateway_with_record: UserGateway):
  56. assert await internal_gateway_with_record.filter([]) == [UserObj(id=12, name="foo")]
  57. async def test_filter_2(internal_gateway_with_record: UserGateway):
  58. assert (
  59. await internal_gateway_with_record.filter([Filter(field="id", values=[1])])
  60. == []
  61. )
  62. async def test_remove(internal_gateway_with_record: UserGateway):
  63. assert await internal_gateway_with_record.remove(12)
  64. assert internal_gateway_with_record.manage.repo.gateway.data == {}
  65. async def test_remove_does_not_exist(internal_gateway: UserGateway):
  66. assert not await internal_gateway.remove(12)
  67. async def test_add_bad_request(internal_gateway: UserGateway):
  68. # a 'bad request' should be reraised as a ValueError; errors in gateways
  69. # are an internal affair.
  70. with pytest.raises(ValueError):
  71. await internal_gateway.add(UserObj(id=12, name=""))
  72. async def test_count(internal_gateway_with_record: UserGateway):
  73. assert await internal_gateway_with_record.count([]) == 1
  74. async def test_count_2(internal_gateway_with_record: UserGateway):
  75. assert (
  76. await internal_gateway_with_record.count([Filter(field="id", values=[1])]) == 0
  77. )
  78. async def test_exists(internal_gateway_with_record: UserGateway):
  79. assert await internal_gateway_with_record.exists([]) is True
  80. async def test_exists_2(internal_gateway_with_record: UserGateway):
  81. assert (
  82. await internal_gateway_with_record.exists([Filter(field="id", values=[1])])
  83. is False
  84. )
  85. async def test_update(internal_gateway_with_record):
  86. updated = await internal_gateway_with_record.update({"id": 12, "name": "bar"})
  87. assert updated == UserObj(id=12, name="bar")
  88. @pytest.mark.parametrize(
  89. "values", [{"id": 12, "name": "bar"}, {"id": None, "name": "bar"}, {"name": "bar"}]
  90. )
  91. async def test_update_does_not_exist(internal_gateway, values):
  92. with pytest.raises(DoesNotExist):
  93. assert await internal_gateway.update(values)
  94. async def test_update_bad_request(internal_gateway_with_record):
  95. # a 'bad request' should be reraised as a ValueError; errors in gateways
  96. # are an internal affair.
  97. with pytest.raises(ValueError):
  98. assert await internal_gateway_with_record.update({"id": 12, "name": ""})
  99. async def test_update_conflict(internal_gateway_with_record):
  100. # a 'conflict' should bubble through the internal gateway
  101. with pytest.raises(Conflict):
  102. assert await internal_gateway_with_record.update({"id": 12, "name": "conflict"})