Typeerror catching classes that do not inherit from baseexception is not allowed
Typeerror catching classes that do not inherit from baseexception is not allowed
Не удается поймать смоделированное исключение, потому что оно не наследует BaseException
Я работаю над проектом, который включает в себя подключение к удаленному серверу, ожидание ответа, а затем выполнение действий на основе этого ответа. Мы перехватываем несколько разных исключений и ведем себя по-разному в зависимости от того, какое исключение перехвачено. Например:
Чтобы проверить это, мы написали тест, подобный следующему
Если я запускаю функцию напрямую, все происходит, как ожидалось. Я даже протестировал, добавив raise requests.exceptions.ConnectionError к предложению try функции. Но когда я запускаю свои юнит-тесты, я получаю
5 ответов
Я мог бы воспроизвести ошибку с минимальным примером:
Тест без насмешек:
Ок, все хорошо, оба теста пройдены
Проблема приходит с издевательствами. Как только класс MyError подвергается насмешке, предложение expect не может ничего перехватить, и я получаю ту же ошибку, что и пример из вопроса:
То есть: исправьте только метод head с исключением как побочный эффект.
Я просто столкнулся с той же проблемой, пытаясь издеваться над sqlite3 (и нашел этот пост, ища решения).
TL / DR: когда вы макетируете полный пакет запросов, предложение исключением заявок.exceptions.ConnectionError пытается поймать макет. Так как макет на самом деле не является BaseException, он вызывает ошибку.
Единственное решение, которое я могу себе представить, это не высмеивать полные запросы, а только те части, которые не являются исключениями. Я должен признать, что не мог найти, как сказать, чтобы издеваться над издеваться над всем, кроме этого
Мое решение состояло в том, чтобы смоделировать весь модуль, а затем установить атрибут mock для исключения равным исключению в реальном классе, эффективно «сняв с себя» исключение. Например, в моем случае:
Для requests вы можете назначать исключения по отдельности, например так:
Или сделайте это для всех requests исключений, подобных этому:
Я не знаю, является ли это «правильным» способом сделать это, но пока мне кажется, что он работает без каких-либо проблем.
Я получаю сообщение об ошибке:
Ошибка типа: перехват классов, которые не наследуются от BaseException, не допускается
Метод, который я хочу протестировать, имеет следующий базовый шаблон:
Тест имеет этот базовый шаблон.
Это похоже на подход, принятый @BillB, но это, безусловно, проще, так как мне не нужно добавлять импорт в мои тесты и все равно работать так же. Мне кажется, это логическое завершение общей цепочки рассуждений в ответах здесь.
Я столкнулся с подобной проблемой, пытаясь издеваться над пакетом sh. Хотя sh очень полезен, тот факт, что все методы и исключения определены динамически, делает их более трудными для насмешек. Итак, следуя рекомендации документации:
Скажем, у нас есть универсальный модуль для тестирования с исключением, которое мы должны были смоделировать:
Can’t catch mocked exception because it doesn’t inherit BaseException
I’m working on a project that involves connecting to a remote server, waiting for a response, and then performing actions based on that response. We catch a couple of different exceptions, and behave differently depending on which exception is caught. For example:
To test this, we’ve written a test like the following
If I run the function directly, everything happens as expected. I even tested by adding raise requests.exceptions.ConnectionError to the try clause of the function. But when I run my unit tests, I get
I tried to change the exception I was patching in to BaseException and I got a more or less identical error.
I’ve read https://stackoverflow.com/a/18163759/3076272 already, so I think it must be a bad __del__ hook somewhere, but I’m not sure where to look for it or what I can even do in the mean time. I’m also relatively new to unittest.mock.patch() so it’s very possible that I’m doing something wrong there as well.
6 Answers 6
Trending sort
Trending sort is based off of the default sorting method — by highest score — but it boosts votes that have happened recently, helping to surface more up-to-date answers.
It falls back to sorting by highest score if no posts are trending.
Switch to Trending sort
I could reproduce the error with a minimal example:
Test without mocking :
Ok, all is fine, both test pass
The problem comes with the mocks. As soon as the class MyError is mocked, the expect clause cannot catch anything and I get same error as the example from the question :
Here I get a first TypeError that you did not have, because I am raising a mock while you forced a true exception with ‘requests.exceptions.ConnectionError’: requests.exceptions.ConnectionError in config. But the problem remains that the except clause tries to catch a mock.
That is : only patch the head method with the exception as side effect.
I just ran into the same issue while trying to mock sqlite3 (and found this post while looking for solutions).
What Serge said is correct:
TL/DR: as you mock the full requests package, the except requests.exceptions.ConnectionError clause tries to catch a mock. As the mock is not really a BaseException, it causes the error.
The only solution I can imagine is not to mock the full requests but only the parts that are not exceptions. I must admit I could not find how to say to mock mock everything except this
My solution was to mock the entire module, then set the mock attribute for the exception to be equal to the exception in the real class, effectively «un-mocking» the exception. For example, in my case:
or do it for all of the requests exceptions like this:
I don’t know if this is the «right» way to do it, but so far it seems to work for me without any issue.
Say we have a generic unit to test with an exception we have to have mocked:
We want to mock CustomError but because it is an exception we run into trouble if we try to patch it like everything else. Normally, a call to patch replaces the target with a MagicMock but that won’t work here. Mocks are nifty, but they do not behave like exceptions do. Rather than patching with a mock, let’s give it a stub exception instead. We’ll do that in our test file.
catching classes that do not inherit from BaseException is not allowed
I’m making a custom plugin to query a database for user info to aide customer support. My backend is slack.
Everytime I start the bot command I’m greeted with:
I’m not sure if this is warning me that I’m attempting to catch an exception that isn’t a BaseClass in my code or if an unknown exception was raised and caught elsewhere outside of my plugin.
To debug I tried:
And I still get the errbot admonition. Note that the command still runs and does the right thing where there is no exception raised by do_the_thing().
1 Answer 1
The Python interpreter should be giving you a full traceback of the exception; the first thing you need to do is find this. It could be occurring in one of two situations. (This is for single-threaded programs; I’m assuming your program is not multithreaded.)
In both cases there should be a stack trace, not just the error message; I’ve confirmed that at least on Python ≥3.4 a stack trace is printed out for case 2.
But more likely it will be something obvious such as:
There is one special case you need to be aware of: if you are seeing messages to stderr (case «2. During finalization,» above) printed out as your program exits that means that the exception was thrown during cleanup as the interpreter shuts down, where random variables throughout the program may have already been set to None as part of the cleanup process. But in this case your program should still exit successfully.
TypeError: catching classes that do not inherit from BaseException is not allowed #849
Comments
slominskir commented Apr 29, 2020
Description
Occasionally I’ll see the following stacktrace as my script closes connections to finish execution (automatically):
How to reproduce
Seems to be transient. Maybe when I delete a schema via the REST interface from the registry and replace it with a new one from a Python script producer? The script works fine, even with the error as the error occurs on connection close after my script has already done what I want.
Checklist
$ pip3 show confluent-kafka
Name: confluent-kafka
Version: 1.4.0
$ pip3 show urllib3
Name: urllib3
Version: 1.25.9
$ cat /etc/redhat-release
Red Hat Enterprise Linux Workstation release 7.7 (Maipo)
The text was updated successfully, but these errors were encountered:
slominskir commented Apr 30, 2020
Looks like modifying the schema during development might be a contributing factor. Perhaps the connectionpool.py class is caching something it shouldn’t? I noticed I spelled a word wrong in an enum type after producing a message, I changed two letters in the symbol that I had inverted and re-ran the producer script expecting to get a schema incompatible error, but instead the message went in fine, but I got a new exception on close:
slominskir commented May 5, 2020 •
Seems newer version of Python (3.7.6) does not have this issue. Or maybe because I upgraded to confluent-kafka 1.4.1 with the newer version of Python?
doctormohamed commented Jun 22, 2020 •
Footer
© 2022 GitHub, Inc.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Python Requests Mock doesn’t catch Timeout exception
I wrote a unittest to test timeout with the requests package
But when it runs, the try block in my_method never catches the requests.exceptions.Timeout
2 Answers 2
Trending sort
Trending sort is based off of the default sorting method — by highest score — but it boosts votes that have happened recently, helping to surface more up-to-date answers.
It falls back to sorting by highest score if no posts are trending.
Switch to Trending sort
There are two problems I see here. One that directly fixes your problem, and the second is a slight misuse of the Mocking framework that further simplifies your implementation.
First, to directly address your issue, based on how you are looking to test your assertion, what you are actually looking to do here:
You should be using a side_effect here to help raise your exception. Per the documentation:
side_effect allows you to perform side effects, including raising an exception when a mock is called
With that in mind, all you really need to do is this:
That should get your exception to raise. However, chances are you might face this error:
This can be best explained by actually reading this great answer about why that is happening. With that answer, taking that suggestion to actually only mock out what you need will help fully resolve your issue. So, in the end, your code will actually look something like this, with the mocked get instead of mocked requests module:
You can now actually further simplify this by making better use of what is in unittest with assertRaises instead of the try/except. This will ultimately just assert that the exception was raised when the method is called. Furthermore, you do not need to create a new method that will raise a timeout, you can actually simply state that your mocked get will have a side_effect that raises an exception. So you can replace that entire def get with simply this:
However, you can actually directly put this in to your patch decorator, so, now your final code will look like this:
Источники информации:
- http://stackoverflow.com/questions/31713054/cant-catch-mocked-exception-because-it-doesnt-inherit-baseexception
- http://stackoverflow.com/questions/46123418/catching-classes-that-do-not-inherit-from-baseexception-is-not-allowed
- http://github.com/confluentinc/confluent-kafka-python/issues/849
- http://stackoverflow.com/questions/36096379/python-requests-mock-doesnt-catch-timeout-exception?lq=1