4

I am trying to test a block of code which interacts with the Amazon Forecast service, which looks very similar to the example provided at https://github.com/aws-samples/amazon-forecast-samples/blob/master/ml_ops/visualization_blog/lambdas/createdataset/dataset.py.

More specifically, I am trying to test that I am handling the exception properly. Assuming 'forecast' is the Amazon Forecast boto3 client, the code is structured as follows:

def example_function(dataset):
    try:
        forecast.describe_dataset(dataset)
        #do some stuff
    except forecast.exceptions.ResourceNotFoundException:
        #do other stuff

I have a test case which looks like this:

from moto.forecast.exceptions import ResourceNotFoundException

@patch('forecast client')
def test(self, mock_forecast):
    mock_forecast.describe_dataset.side_effect = ResourceNotFoundException
    example_function(dataset)

This produces the 'TypeError: catching classes that do not inherit from BaseException is not allowed' which is confusing me, as moto.forecast.exceptions.ResourceNotFoundException inherits the moto class 'AWSError', which in turn inherits 'Exception'.

I am fairly at a loss as to how to test the 'except' block of my code without actually interacting with the forecast service if I am not able to set a side_effect as an Exception. Any ideas would be greatly appreciated!

ratiugo
  • 53
  • 1
  • 4
  • "which in turn inherits `Exception`." but still not the `BaseException` – Arseniy Feb 05 '21 at 20:04
  • That makes sense - I pulled both classes out of the moto docs and changed the AWSError class to inherit 'BaseException' and the problem still persists. – ratiugo Feb 05 '21 at 20:11
  • You need to pass an exception instance, not a class, e.g. `side_effect = ResourceNotFoundException()`. Ah, and `Excpetion` is derived from `BaseException`. – MrBean Bremen Feb 05 '21 at 20:17
  • @MrBeanBremen thanks for the advice - I tried ResourceNotFoundException(), which told me 'TypeError: __init__() missing 1 required positional argument: 'message', and I then changed it to 'ResourceNotFoundException(message='hi')', which reproduced the original problem. – ratiugo Feb 05 '21 at 20:27
  • Hm, that's strange - I have used it that way. You could also use the list form, e.g. `side_effect = [ResourceNotFoundException("hi)]`, but I don't think it will make difference... – MrBean Bremen Feb 05 '21 at 20:59
  • @MrBeanBremen what is truly tragic is that print(issubclass(ResourceNotFoundException, BaseException)) prints 'True' - I appreciate the help though! – ratiugo Feb 05 '21 at 21:18
  • The boto3-client only throws botocore.exeptions.ClientError, as far as I know, so you might have more luck catching that. The boto3-client will convert any Moto-specific exception into a ClientError anway. – Bert Blommers Mar 29 '21 at 12:54
  • Also: Moto doesn't support the 'describe_dataset' method yet - I don't know whether that makes any difference. – Bert Blommers Mar 29 '21 at 12:58

1 Answers1

2

The problem probably is you overwritten the original forecast object with a mock and it returns a mock object to forecast.exceptions.ResourceNotFoundException in the example function when checking the exception branches.

So you have to modify the test to something like this:

from moto.forecast.exceptions import ResourceNotFoundException

@patch('forecast client')
def test(self, mock_forecast):
    mock_forecast.exceptions.ResourceNotFoundException = ResourceNotFoundException
    mock_forecast.describe_dataset.side_effect = ResourceNotFoundException("Exception message")
    example_function(dataset)
Eqzt111
  • 487
  • 6
  • 17