Python:当涉及Try-Except时,断言引发自定义异常的单元测试失败

Python:当涉及Try-Except时,断言引发自定义异常的单元测试失败,python,unit-testing,exception,try-catch,Python,Unit Testing,Exception,Try Catch,我正在尝试编写一个单元测试,它断言嵌套的自定义异常是由函数引发的 下面的示例代码通过: from unittest import TestCase class MyClass(): class MyException(Exception): pass def fail(): raise MyClass.MyException() class MyTests(TestCase): def test_throwsException(self):

我正在尝试编写一个单元测试,它断言嵌套的自定义异常是由函数引发的

下面的示例代码通过:

from unittest import TestCase


class MyClass():
    class MyException(Exception):
        pass


def fail():
    raise MyClass.MyException()


class MyTests(TestCase):
    def test_throwsException(self):
        with self.assertRaises(MyClass.MyException):
            fail()
但是,当我的提升代码涉及try except时,我的测试失败:

from unittest import TestCase
from enum import Enum


class Weekdays(Enum):
    MONDAY = 'mon'
    TUESDAY = 'tue'
    WEDNESDAY = 'wed'        
    THURSDAY = 'thu'        
    FRIDAY = 'fri'        

    class InvalidValue(Exception):
        pass


def parse(key: str) -> Weekdays:
    try:
        return Weekdays(key)
    except Exception as e:
        raise Weekdays.InvalidValue() from e


class MyTests(TestCase):
    def test_throwsException(self):
        with self.assertRaises(Weekdays.InvalidValue):
            parse('invalid')
它返回以下错误:

E
======================================================================
ERROR: test_throwsException (test_main.MyTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "E:\PythonCodes\playground\test_main.py", line 25, in test_throwsException
    with self.assertRaises(Weekdays.InvalidValue):
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python38\lib\unittest\case.py", line 816, in assertRaises
    return context.handle('assertRaises', args, kwargs)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python38\lib\unittest\case.py", line 187, in handle
    raise TypeError('%s() arg 1 must be %s' %
TypeError: assertRaises() arg 1 must be an exception type or tuple of exception types

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)
我不太明白arg 1必须是异常类型的含义,因为我假设我的自定义异常是异常类型


为什么第二个版本的try-except失败了?

问题是您已经将异常类的定义嵌套在枚举中:

class Weekdays(Enum):
    MONDAY = 'mon'
    TUESDAY = 'tue'
    WEDNESDAY = 'wed'        
    THURSDAY = 'thu'        
    FRIDAY = 'fri'        

    class InvalidValue(Exception):
        pass
enum(通过元类欺骗)将其类属性设置为enum类的单个实例,使用您在该enum实例的
.value
内的定义中指定给属性的值。就像在枚举中定义的其他类属性一样。因此,考虑一下:

In [1]: from enum import Enum

In [2]:
   ...: class Weekdays(Enum):
   ...:     MONDAY = 'mon'
   ...:     TUESDAY = 'tue'
   ...:     WEDNESDAY = 'wed'
   ...:     THURSDAY = 'thu'
   ...:     FRIDAY = 'fri'
   ...:
   ...:     class InvalidValue(Exception):
   ...:         pass
   ...:

In [3]: Weekdays.MONDAY
Out[3]: <Weekdays.MONDAY: 'mon'>

In [4]: Weekdays.MONDAY.value
Out[4]: 'mon'

In [5]: Weekdays.InvalidValue
Out[5]: <Weekdays.InvalidValue: <class '__main__.Weekdays.InvalidValue'>>

In [6]: Weekdays.InvalidValue.value
Out[6]: __main__.Weekdays.InvalidValue
同样,在
解析中,您需要:

raise Weekdays.InvalidValue.value() from e

但是您最好只在模块级别定义
InvalidValue

为什么要在枚举中定义异常类?这将使您在
工作日.InvalidValue
中访问的内容成为具有该类属性的
.value
的枚举。。。就像在枚举中定义的任何其他类属性一样。把它从枚举中删除。嗯,我明白了!这确实解决了问题。似乎枚举类中不能有嵌套类。你能加上这个作为回答吗?这样我就可以接受了?顺便说一下,为了组织的目的,我嵌套了我的自定义异常。嗯,它们可以。但是嵌套类并不是什么特别的事情,它相当于
my_attribute=SomeClass
。通常,嵌套类在Python中不是常见的模式。这真的没有什么优势。代码组织的基本单位是模块。我最近看到了一些关于python中嵌套类的问题。我认为对于嵌套类的工作方式有一个常见的误解,即它们根本不从它们所在的类继承任何东西。也许有人可以在这方面纠正我,但我能看到的嵌套类的唯一好处是组织名称空间。然后,当外部类更改属性访问的工作方式时,即使这样也可能会退出窗口。@Aaron是的,将一个类定义粘贴到另一个类定义的主体中的唯一效果是,生成的类对象位于它嵌套的类的命名空间中。当然,对于元类,各种各样的欺骗都可能发生,如上所示。我曾经使用过一两次嵌套类,我相信它们在Django中使用过(Django严重依赖元类魔法)。但它几乎总是比它的价值更麻烦。如果一个类是“private”并且不应该公开,只需将它放在模块级别并使用一个下划线,这就是Pythonic约定。
raise Weekdays.InvalidValue.value() from e