Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

db.query(User).filter(User.id = id).first() always return None #234

Open
alexnguyen2201 opened this issue Jun 4, 2022 · 2 comments
Open
Labels
bug Something isn't working

Comments

@alexnguyen2201
Copy link

Describe the bug
It's fine if sfwafawfcwafawf but first:

db.query(User).filter(User.id = id).sfwafawfcwafawf()= 112

but first:

db.query(User).filter(User.id = id).first() = None

To Reproduce
For example:

    def test_find_user():
        db = UnifiedAlchemyMagicMock()
        db.query.return_value.filter.return_value.first.return_value = 112
        UserRepository(db).find_user(id=1)
        assert 0

and

    def find_user(id: int) -> None:
        print("result of mock db:", db.query(User).filter(User.id = id).first())

Expected behavior
If i set: db.query.return_value.filter.return_value.first.return_value = 112

So the result of db.query().filter().first() should be 112

Screenshots
If applicable, add screenshots to help explain your problem.
target user randon user()
def is user following for another(
Screen Shot 2022-06-04 at 16 11 04

  • OS: MacOS Monterey
  • Version 12.3.1
@alexnguyen2201 alexnguyen2201 added the bug Something isn't working label Jun 4, 2022
@facundopadilla
Copy link

facundopadilla commented Dec 9, 2022

I have the same problem!
OS: Kubuntu 22.04
Version: mock-alchemy==0.2.5

@facundopadilla
Copy link

facundopadilla commented Dec 9, 2022

I think I found the error but I am not sure if it is this one:

  • mock_alchemy/mocking.py in line 620:
for calls, result in sorted_mock_data:
    calls = [
        sqlalchemy_call(
            i,
            with_name=True,
            base_call=self.unify.get(i[0]) or Call,
        )
        for i in calls
    ]
    if all(c in previous_calls for c in calls):  # line 620
        return self.boundary[_mock_name](result, *args, **kwargs)

This check if the some call exists in previous_calls (created in line 590)

For example, in my case I have this:

  • Calls: [call.query(User), call.filter(User.username == "test"), call.first()]
  • Return value: [User(id=1, username="test", password="test")]

Code:

session = UnifiedAlchemyMock(
    data=[([call.query(User), call.filter(User.username == "test"), call.first()], [User(id=1, username="test", password="test")])]
)

When line 620 is to be executed, the previous_calls has this:

[
    call.filter(BinaryExpression(sql='users.username = :username_1', params={'username_1': 'test'})),
    call.query(<class 'project.models.users.User'>), 
    call.__len__(),
    call.__str__(),
    call.__len__()
]

The call first() is not added in previous_calls, then it fails.

I guess it must be because the first() is not a method of sqlalchemy as such, i.e. as a query, but it is a method of the same object that returns the filter and returns the first of the list as if it were a slicing (any_list[0])

# sqlalchemy/orm/query.py - line 2799
def first(self):
    if self._statement is not None:
        return self._iter().first()
    else:
        return self.limit(1)._iter().first()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants