Skip to content

Overriding does not work with non-primitive type objects in Litestar #122

Closed

Description

@nightblure

I found a new test case. This is more of a Litestar problem, but still

Non-primitive objects cannot be overridden with any other type until we mark it with the Any annotation. Below is the code that will help reproduce this


class and container:

class SomeService:
    def do_smth(self) -> str:
        return "something"


class DIContainer(BaseContainer):
    bool_fn = providers.Factory(bool_fn, value=False)
    str_fn = providers.Factory(str_fn)
    list_fn = providers.Factory(list_fn)
    int_fn = providers.Factory(int_fn)
    some_service = providers.Factory(SomeService)

controller handler:

    @get(path="mock_overriding", dependencies={"some_service": Provide(DIContainer.some_service)})
    # does not works with some_service: SomeService type, but works with some_service: SomeService | Any
    async def mock_overriding_endpoint_handler(self, some_service: SomeService) -> dict[str, typing.Any]:
        return {"object": some_service.do_smth()}

test:

def test_litestar_endpoint_with_mock_overriding() -> None:
    some_service_mock = Mock(do_smth=lambda: "mock func")

    with DIContainer.some_service.override_context(some_service_mock), TestClient(app=app) as client:
        response = client.get("/router/controller/mock_overriding")

    assert response.json()["object"] == "mock func"

error:

TypeError: Unsupported type: <class 'unittest.mock.Mock'>
msgspec.ValidationError: Unsupported type: <class 'unittest.mock.Mock'> - at `$.some_service`

Activity

  1. lesnik512 commented on Nov 19, 2024

    @lesnik512
    Member

    @nightblure Found another hack here litestar-org/litestar#2597 (comment)

    Can be fixed by adding Dependency(skip_validation=True) like this:

    @get(path="mock_overriding", dependencies={"some_service": Provide(DIContainer.some_service)})
    async def mock_overriding_endpoint_handler(self, some_service: typing.Annotated[SomeService, Dependency(skip_validation=True)]) -> dict[str, typing.Any]:
        return {"object": some_service.do_smth()}

    I think we need to document this behaviour and that's it. What do you think?

  2. nightblure commented on Nov 19, 2024

    @nightblure
    ContributorAuthor

    @lesnik512
    It doesn't look that convenient, but it's good that it works

    I can add this to the documentation with examples and tests

  3. lesnik512 commented on Nov 19, 2024

    @lesnik512
    Member

    @nightblure would be great 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinglitestar

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions