text: Title: RuntimeError During Pytest Collection Because no App Context is Set Up Yet
  Body: ## Current Behavior
  
  My application uses the factory method for setting up the application, so I use a pattern similar to the following:
  ```python
  # ./api/__init__.py
  
  from flask import Flask
  from flask_sqlalchemy import SQLAlchemy
  
  db = SQLAlchemy()
  
  def create_app():
      app = Flask(__name__)
      db.init_app(app)
  ```
  
  When collecting tests, pytest imports the test files as defined by in the pytest settings (in my case, the `pytest.ini` specifies that all `test_*` files in the directory `./tests` are collected). During the collection, the test files are imported before any of the fixtures are set up. I have a file which defines a model which is subclassed from `api.db.Model`. My test makes use of this model by using sqlalchemy to scan the database to evaluate the precondition. Something like this: 
  
  ```python
  from api.models import User
  
  def it_creates_a_user(self, session):
      # GIVEN there is no existing user
      assert session.query(User).count() == 0
  ```
  
  So when this file is imported, the `api.models.__init__.py` file is imported which, in turn, imports `api.models.user.User` which has a definition similar to the following:
  
  ```python
  from api import db
  
  class User(db.Model):
      # columns
  ```
  
  Again, when this import happens, pytest has not yet created the app fixture where I push the app_context, which means flask_sqlalchemy does not know which app the db is bound to and so it raises a `RuntimeError`:
  
  ```
  RuntimeError: No application found. Either work inside a view function or push an application context. See http://flask-sqlalchemy.pocoo.org/contexts/.
  ```
  
  This perplexed me greatly at first since I definitely am pushing an application context in my app fixture:
  
  ```python
  @pytest.fixture(scope="session", autouse=True)
  def app():
      logger.info("Creating test application")
      test_app = create_app()
      with test_app.app_context():
          yield test_app
  ```
  
  It wasn't until I thought to run `pytest --continue-on-collection-errors` that I found that the tests all run and pass just fine after the RuntimeError is raised during the collection phase. It was then that it dawned on me what the cause of the issue was. I have worked around this issue by pushing the context in my `tests/__init__.py` file:
  
  ```python
  # ./tests/__init__.py
  
  from api import create_app
  
  """
  This is a workaround for pytest collection of flask-sqlalchemy models.
  When running tests, the first thing that pytest does is to collect the
  tests by importing all the test files. If a test file imports a model,
  as they will surely do, then the model tries to use the api.db before
  the app has been created. Doing this makes flask-sqlalchemy raise a
  RuntimeError saying that there is no application found. The following
  code only exists to set the app context during test import to avoid
  this RuntimeError. The tests will us the app fixture which sets up the
  context and so this has no effect on the tests when they are run.
  """
  
  app = create_app()
  app.app_context().push()
  ```
  
  This feels a little dirty and I'm hopeful that there is a way for this issue to be solved.
  
  ### Relevant Code
  
  ```toml
  # pyproject.toml
  
  # Unrelated items
  
  [tool.pytest.ini_options]
  minversion = "6.0"
  log_auto_indent = true
  log_cli = true
  log_cli_format = "%(levelname)-5.5s [%(name)s] %(message)s"
  testpaths = ["tests"]
  python_functions = ["test_*", "it_*"]
  ```
  
  ```python
  # api/__init__.py
  
  import os
  import shlex
  import subprocess
  
  from dotenv import load_dotenv
  from flask import Flask
  from flask_marshmallow import Marshmallow
  from flask_sqlalchemy import SQLAlchemy
  
  db = SQLAlchemy()
  ma = Marshmallow()
  
  
  def create_app(test_config=None):
      app = Flask(__name__, instance_relative_config=True)
  
      if test_config is None:
          app.config.from_object(os.getenv("APP_SETTINGS"))
      else:
          app.config.from_mapping(test_config)
  
      db.init_app(app)
      ma.init_app(app)
  
      # a simple page that says hello
      @app.route("/health-check")
      def health_check():  # pragma: no cover
          cmd = "git describe --always"
          current_rev = subprocess.check_output(shlex.split(cmd)).strip()
          return current_rev
  
      return app
  ```
  
  ```python
  # ./app/models/__init__.py
  
  from .user import User
  ```
  
  ```python
  # ./api/models/user.py
  
  from uuid import uuid4
  
  from sqlalchemy_utils import EmailType, UUIDType
  
  from api import db
  
  
  class User(db.Model):
      id = db.Column(UUIDType, primary_key=True, default=uuid4)
      email = db.Column(EmailType, nullable=False)
  
      def __repr__(self):
          return f"<User: {self.email}>"
  ```
  
  ```python
  # ./tests/unit/models/test_user.py
  
  import logging
  
  import pytest
  import sqlalchemy
  
  from api.models import User  # pytest imports this line before it sets up any fixtures
  
  logger = logging.getLogger(__name__)
  
  
  class TestUserModel:
      class TestNormalCase:
          def it_creates_a_user(self, session):
              # GIVEN No user exists in our database
              assert session.query(User).count() == 0
  
              # WHEN we add a new user
              test_user = User(email="test@testing.com")
              session.add(test_user)
              session.commit()
  
              # THEN the user is persisted in the database
              actual_user = session.query(User).get(test_user.id)
              assert actual_user == test_user
              assert repr(actual_user) == f"<User: {test_user.email}>"
  
      class TestErrorCase:
          def it_requires_a_user_email(self, session):
              with pytest.raises(sqlalchemy.exc.IntegrityError):
                  test_user = User()
                  session.add(test_user)
                  session.commit()
  ```
  
  ```python
  # ./tests/conftest.py
  
  # other stuff here, just showing that I am using the context in my app fixture
  
  @pytest.fixture(scope="session", autouse=True)
  def app():
      logger.info("Creating test application")
      test_app = create_app()
      with test_app.app_context():
          yield test_app
  ```
  
  Environment:
  
  - Python version: `3.9.1`
  - Flask-SQLAlchemy version: `2.4.4`
  - SQLAlchemy version: `1.3.23`
  