I want to do a unittest with pytest for this method:
class UserService:
@classmethod
async def get_user_by_login(cls, session: SessionDep, login: str) -> Optional[User]:
sql = select(User).where(User.login == login)
result = await session.exec(sql)
return result.first()
I have already this test:
@pytest.mark.asyncio
async def test_get_user_by_login(mocker):
# Arrange
mock_exec_result = AsyncMock(return_value=None)
mock_session = mocker.AsyncMock()
mock_session.exec.return_value = mock_exec_result
sql_request = select(User).where(User.login == LOGIN)
# Act
await UserService.get_user_by_login(mock_session, LOGIN)
# Assert
mock_session.exec.assert_called_once_with(sql_request)
mock_session.exec.assert_called_once()
mock_exec_result.first.assert_called_once_with()
But I want to test sql_request variable with assert_called_once_with and it obviously fail because these are not the same object instance...
See the logs:
# Assert
> mock_session.exec.assert_called_once_with(sql_request)
E AssertionError: expected call not found.
E Expected: exec(<sqlmodel.sql._expression_select_cls.SelectOfScalar object at 0x0000028478A0EFC0>)
E Actual: exec(<sqlmodel.sql._expression_select_cls.SelectOfScalar object at 0x0000028478884B00>)
E
E pytest introspection follows:
E
E Args:
E assert (<sqlmodel.sql._expression_select_cls.SelectOfScalar object at 0x0000028478884B00>,) == (<sqlmodel.sql._expression_select_cls.SelectOfScalar object at 0x0000028478A0EFC0>,)
E
E At index 0 diff: <sqlmodel.sql._expression_select_cls.SelectOfScalar object at 0x0000028478884B00> != <sqlmodel.sql._expression_select_cls.SelectOfScalar object at 0x0000028478A0EFC0>
E
E Full diff:
E (
E - <sqlmodel.sql._expression_select_cls.SelectOfScalar object at 0x0000028478A0EFC0>,
E ? ^ ---
E + <sqlmodel.sql._expression_select_cls.SelectOfScalar object at 0x0000028478884B00>,
E ? ^^^^
E )
__eq__method and use those withassert_called_once_withto apply whatever logic you want to deciding if the real value is correct - stackoverflow.com/a/64973325/3001761.