[Django] django.db.transaction.TransactionManagementError

Nam Eun-Ji·2022년 2월 24일
0

ERROR

목록 보기
1/2

상황

django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

  • django 단위 테스트 중 django.db.transaction.TransactionManagementError가 났다.
  • error가 난 부분은 unique한 필드(phone)를 체크하는 부분(Integrity Error 예외처리)이었다.
  • print문을 통해 확인해봤더니user.testsself.assertEqual() 은 다 통과했다.
  • 코드는 아래와 같다.
# user.tests
class UserSignUpTest(TestCase):
    def setUp(self):
        self.client = Client()
        User.objects.create(
            nickname='user1',
            phone='010111110000',
            password=bcrypt.hashpw('user1111'.encode('utf-8'), bcrypt.gensalt()).decode('utf-8'),
            is_staff=False
        )
        User.objects.create(
            nickname='admin1',
            phone='01099999999',
            password=bcrypt.hashpw('admin1234'.encode('utf-8'), bcrypt.gensalt()).decode('utf-8'),
            is_staff=True
        )

    def tearDown(self):
        User.objects.all().delete()
    
    def test_fail_duplicate_phone(self):
        data = {
            "nickname": "user3",
            "phone": "010111110000",
            "password": "user3333",
            "is_staff": False
        }
        response = self.client.post("/user/signup/", data=data, content_type="application/json")
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.json(), {"message": "DUPLICATE_PHONE"})
# user.views
class SignUpView(APIView):
    @swagger_auto_schema(tags=["Sign Up"], request_body=UserSerializer, responses={201: 'Success'})
    def post(self, request):
        try:
            data = json.loads(request.body)

            if check_length(data["nickname"], 2):
                return JsonResponse({"message": "NICKNAME_SHORT"}, status=400)

            if check_length(data["phone"], 10):
                return JsonResponse({"message": "PHONE_SHORT"}, status=400)

            if check_password(data["password"]):
                return JsonResponse({"message": "INVALID_PASSWORD"}, status=400)

            User(
                phone=data["phone"],
                nickname=data["nickname"],
                password=hash_password(data["password"]).decode("utf-8"),
                is_staff=data["is_staff"]
            ).save()

            return HttpResponse(status=201)

        except IntegrityError:
            return JsonResponse({"message": "DUPLICATE_PHONE"}, status=400)
        except KeyError:
            return JsonResponse({"message": "INVALID_KEYS"}, status=400)



원인

참고 글을 보니
1. TestCase는 transaction내에서 실행됨.
2. IntegrityError가 발생하면 현재 transaction이 손상됨.



해결

TestCase 대신 TransactionTestCase 사용



참고사이트
1. https://stackoverflow.com/questions/24588520/testing-several-integrityerrors-in-the-same-django-unittest-test-case/24589930
2. https://ondemand.tistory.com/328

profile
한 줄 소개가 자연스러워지는 그날까지

0개의 댓글