Flask中的模型的ClassMethod的单元测试

时间:2020-03-16 14:28:47

标签: python python-3.x flask flask-sqlalchemy

我有两个数据库:一个是master,为了测试,我有另一个数据库master_test

要从表格中检索总价,我在模型中创建了@classmethod。这种方法可以帮助我获得按月和年过滤的价格总和。这是类方法:

@classmethod
def get_total_book_price(cls, id):

    query = Book.query.with_entities(
        func.sum(Book.price).label("price")
    ).filter(
        extract('year', Book.created_at) >= datetime.date.today().year,
        extract('month', Book.created_at) >= datetime.date.today().month
    ).filter(
        Book.id == id
    ).all()

    return query[0].price

此查询效果很好。但是,当我在测试用例中运行它时,它显示的master数据库不存在。它应该找到master_test数据库而不是master数据库。 这是测试代码:

def test_get_total_book_price(self):
    id = 1
    response = Book.get_total_book_price(id)
    if not response:
        self.assertEqual(response, False)
    self.assertEqual(response, True)

显示错误:

 sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) FATAL:  database "master" 
 does not exist
 (Background on this error at: http://sqlalche.me/e/e3q8)
 ----------------------------------------------------------------------
 Ran 34 tests in 2.011s
 FAILED (errors=1)
 ERROR: Job failed: exit code 1

其他一些测试用例可以与master_test一起很好地工作。但是对于此测试,为什么要寻找master数据库?

1 个答案:

答案 0 :(得分:0)

您必须提供测试功能的上下文。最好的方法是与工厂合作。如何执行此操作的绝佳说明是:http://alanpryorjr.com/2019-05-20-flask-api-example/。如果您有一个应用程序和一个数据库夹具,则可以在测试功能中使用它:

class TenantPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
      scope.all
    end
  end

  def show?
    admin? || (agency? && user.agency.tenants.include?(record)) || (tenant? && user.tenant == record)
  end

  def index?
    admin? || (agency? && (record - user.agency.tenants).empty?)
  end

  def create?
    admin? || (agency? && user.agency.properties.include?(record.property))
  end

  def update?
    admin?
  end

  def destroy?
    admin? || (agency? && user.agency.tenants.include?(record))
  end
end

是的,唯一的区别是函数调用中的 db 。我不能说为什么您的其他测试仍然有效。我最好的猜测是,失败的测试将在测试上下文被破坏之后执行。最好每次都清楚地了解您的应用上下文。

如果其他所有操作均失败(并且您可以通过正确的数据库连接访问应用程序),则可以使用以下方式手动推送上下文:

from test.fixtures import app, db

def test_get_total_book_price(self, db):
    id = 1
    response = Book.get_total_book_price(id)
    if not response:
        self.assertEqual(response, False)
    self.assertEqual(response, True)

我想强调一下,您应该使用工厂进行测试。

参考:https://flask.palletsprojects.com/en/1.0.x/appcontext/

相关问题