在Playwright同步测试中调用Django同步方法create_user()报错的解决咨询
在Playwright同步测试中调用Django同步方法create_user()报错的解决咨询
嘿,我来帮你捋捋这个问题的解决思路~
首先得搞清楚为什么会出现这个错误:你用的是Playwright的同步API(sync_playwright),但它底层其实是靠asyncio事件循环实现的,这就导致你的测试函数虽然看起来是同步的,但实际运行时处于异步上下文中。而Django的ORM方法(比如create_user())是同步操作,默认不允许在异步上下文里直接调用,所以就触发了SynchronousOnlyOperation错误。
你提到用sync_to_async没法await,是因为你的测试函数是同步的,不能直接用await语法。那我们可以用下面两种方法解决:
方法1:用asyncio.run()包裹异步调用
把create_user()用sync_to_async包装成异步方法,然后在同步函数里用asyncio.run()来执行这个异步操作,代码示例如下:
from asgiref.sync import sync_to_async import asyncio from django.contrib.auth.models import User class TC(TestCase): @playwright_test def test_login(self): # 定义异步函数来创建用户 async def create_test_user(): return await sync_to_async(User.objects.create_user)( username="test_user", email="test@example.com", password="test_pass123" ) # 在同步测试函数里运行异步创建用户的逻辑 user = asyncio.run(create_test_user()) # 继续你的Playwright测试流程 self.page.goto(self.host) self.page.fill("#username", user.username) # ... 剩下的测试代码
方法2:用线程池执行同步的创建用户操作
因为Django允许在独立线程里执行同步ORM操作,我们可以用Python的ThreadPoolExecutor来把create_user()放到单独线程里运行,避免异步上下文的限制:
from concurrent.futures import ThreadPoolExecutor from django.contrib.auth.models import User class TC(TestCase): @playwright_test def test_login(self): # 定义同步的创建用户函数 def create_user_sync(): return User.objects.create_user( username="test_user", email="test@example.com", password="test_pass123" ) # 用线程池执行并获取结果 with ThreadPoolExecutor() as executor: user = executor.submit(create_user_sync).result() # 后续Playwright操作 self.page.goto(self.host) # ... 你的测试代码
两种方法都能解决问题,你可以根据自己的习惯选择~ 另外要注意,如果你用sync_to_async,默认thread_sensitive=True,会保留Django的数据库连接上下文,不用额外配置。
备注:内容来源于stack exchange,提问作者Barney Szabolcs
相关产品推荐
相关产品推荐

