You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@nifi.apache.org by Russell Bateman <ru...@perfectsearchcorp.com> on 2016/08/25 16:51:12 UTC

Unable to catch ProcessException error in JUnit test code

 From my custom processor, I'm throwing a ProcessException that never 
reaches my catch in the JUnit test. I already have several other JUnit 
tests working on this processor; this is the remaining wiggle I want to 
test.

I might be blind here, but I can't see what's wrong. Any comment will be 
useful.

Thanks,

Russ

Here's the tail-end of my processor'sonTrigger() method:

     ...

     try
     {
       X12Simple x12 = ( X12Simple ) parser.parse( is.get() );
       ...

       session.transfer( newFlowfile, resultingRelationship );
     }
     catch( FormatException e ) *// this exception is caught--was thrown 
in X12 parser as expected!*
     {
       session.remove( newFlowfile );
*      throw new ProcessException( e + " (the content is unparsable as 
an X12 message)" );*
     }
     catch( IOException e )
     {
       session.remove( newFlowfile );
       throw new ProcessException( e );
     }
   }
   finally
   {
     session.transfer( flowfile, ORIGINAL );
   }
}


And here's the JUnit test case for now:

@Test
public void testOnTriggerCompleteCrap()
{
   TestRunner runner = TestRunners.newTestRunner( new X12MessageRouter() );

   final int         ONE     = 1;
   final InputStream MESSAGE = new ByteArrayInputStream( _CRAP.getBytes() );

   Map< String, String > flowFileAttributes = new HashMap<>();
   flowFileAttributes.put( "testname", "X12 Message Router Unit Test" );

   runner.setValidateExpressionUsage( false );
   runner.enqueue( MESSAGE, flowFileAttributes );

   try
   {
*runner.run( ONE ); **// (exception will happen under here)*
     runner.assertQueueEmpty();
     List< MockFlowFile > results = runner.getFlowFilesForRelationship( 
X12MessageRouter.NONE );
   }
   catch( ProcessException e )
   {
     int x = 9; *// (never caught at breakpoint set here)*
   }
}


Re: Unable to catch ProcessException error in JUnit test code

Posted by Matt Burgess <ma...@gmail.com>.
You won't need a try/catch in your unit test, the runner.run(ONE)
should finish "successfully", then you can do the getLogger() and
check the message. If the error message is only logged if a
ProcessException is thrown (like with the suffix I see in your code),
then you should be able to check for its presence/absence.

On Thu, Aug 25, 2016 at 1:35 PM, Russell Bateman
<ru...@perfectsearchcorp.com> wrote:
> Yes, but as I never regain control after throwing ProcessorErrorin
> onTrigger(), I don't get a chance to look at the resulting log in my unit
> test. I must still be missing something here?
>
>
>
> On 08/25/2016 11:29 AM, Matt Burgess wrote:
>>
>> Russ,
>>
>> You can call runner.getLogger() which gives you a MockComponentLog:
>>
>> https://github.com/apache/nifi/blob/master/nifi-mock/src/main/java/org/apache/nifi/util/MockComponentLog.java.
>>  From that you can get your messages and check if you logged the
>> specific one(s) you care about.
>>
>> Regards,
>> Matt
>>
>> On Thu, Aug 25, 2016 at 1:22 PM, Russell Bateman
>> <ru...@perfectsearchcorp.com> wrote:
>>>
>>> Matt,
>>>
>>> Thank you for replying. It extends AbstractProcessor:
>>>
>>> public class X12MessageRouter extends AbstractProcessor
>>> {
>>>    @Override
>>>    public void onTrigger( final ProcessContext context, final
>>> ProcessSession
>>> session ) throws ProcessException
>>>    {
>>>      FlowFile flowfile = session.get();
>>>      ...
>>>
>>> No, you're right, I don't want to propagate exceptions outside the
>>> processor. I wasn't even thinking about that. I really just wanted to
>>> test
>>> that I'm throwing ProcessorException with the specific message for the
>>> specific reason I'm throwing it. Do you have a suggestion based on this?
>>>
>>> Thanks,
>>>
>>> Russ
>>>
>>>
>>> On 08/25/2016 11:12 AM, Matt Burgess wrote:
>>>>
>>>> Does your processor extend AbstractProcessor or
>>>> AbstractSessionFactoryProcessor? If the former, then all throwables
>>>> get caught by the onTrigger method:
>>>>
>>>>
>>>> https://github.com/apache/nifi/blob/master/nifi-api/src/main/java/org/apache/nifi/processor/AbstractProcessor.java
>>>>
>>>> Are you sure you want such exceptions to propagate out of the
>>>> processor? Usually you would route a flow file to some failure or
>>>> retry relationship, or rollback the session (which is what
>>>> AbstractProcessor does). This keeps the integrity of the framework
>>>> rather than an exception escaping into the wild.
>>>>
>>>> Regards,
>>>> Matt
>>>>
>>>> On Thu, Aug 25, 2016 at 12:51 PM, Russell Bateman
>>>> <ru...@perfectsearchcorp.com> wrote:
>>>>>
>>>>>   From my custom processor, I'm throwing a ProcessException that never
>>>>> reaches
>>>>> my catch in the JUnit test. I already have several other JUnit tests
>>>>> working
>>>>> on this processor; this is the remaining wiggle I want to test.
>>>>>
>>>>> I might be blind here, but I can't see what's wrong. Any comment will
>>>>> be
>>>>> useful.
>>>>>
>>>>> Thanks,
>>>>>
>>>>> Russ
>>>>>
>>>>> Here's the tail-end of my processor'sonTrigger() method:
>>>>>
>>>>>       ...
>>>>>
>>>>>       try
>>>>>       {
>>>>>         X12Simple x12 = ( X12Simple ) parser.parse( is.get() );
>>>>>         ...
>>>>>
>>>>>         session.transfer( newFlowfile, resultingRelationship );
>>>>>       }
>>>>>       catch( FormatException e ) *// this exception is caught--was
>>>>> thrown
>>>>> in
>>>>> X12 parser as expected!*
>>>>>       {
>>>>>         session.remove( newFlowfile );
>>>>> *      throw new ProcessException( e + " (the content is unparsable as
>>>>> an
>>>>> X12 message)" );*
>>>>>       }
>>>>>       catch( IOException e )
>>>>>       {
>>>>>         session.remove( newFlowfile );
>>>>>         throw new ProcessException( e );
>>>>>       }
>>>>>     }
>>>>>     finally
>>>>>     {
>>>>>       session.transfer( flowfile, ORIGINAL );
>>>>>     }
>>>>> }
>>>>>
>>>>>
>>>>> And here's the JUnit test case for now:
>>>>>
>>>>> @Test
>>>>> public void testOnTriggerCompleteCrap()
>>>>> {
>>>>>     TestRunner runner = TestRunners.newTestRunner( new
>>>>> X12MessageRouter()
>>>>> );
>>>>>
>>>>>     final int         ONE     = 1;
>>>>>     final InputStream MESSAGE = new ByteArrayInputStream(
>>>>> _CRAP.getBytes()
>>>>> );
>>>>>
>>>>>     Map< String, String > flowFileAttributes = new HashMap<>();
>>>>>     flowFileAttributes.put( "testname", "X12 Message Router Unit Test"
>>>>> );
>>>>>
>>>>>     runner.setValidateExpressionUsage( false );
>>>>>     runner.enqueue( MESSAGE, flowFileAttributes );
>>>>>
>>>>>     try
>>>>>     {
>>>>> *runner.run( ONE ); **// (exception will happen under here)*
>>>>>       runner.assertQueueEmpty();
>>>>>       List< MockFlowFile > results =
>>>>> runner.getFlowFilesForRelationship(
>>>>> X12MessageRouter.NONE );
>>>>>     }
>>>>>     catch( ProcessException e )
>>>>>     {
>>>>>       int x = 9; *// (never caught at breakpoint set here)*
>>>>>     }
>>>>> }
>>>>>
>

Re: Unable to catch ProcessException error in JUnit test code

Posted by Russell Bateman <ru...@perfectsearchcorp.com>.
Yes, but as I never regain control after throwing ProcessorErrorin 
onTrigger(), I don't get a chance to look at the resulting log in my 
unit test. I must still be missing something here?


On 08/25/2016 11:29 AM, Matt Burgess wrote:
> Russ,
>
> You can call runner.getLogger() which gives you a MockComponentLog:
> https://github.com/apache/nifi/blob/master/nifi-mock/src/main/java/org/apache/nifi/util/MockComponentLog.java.
>  From that you can get your messages and check if you logged the
> specific one(s) you care about.
>
> Regards,
> Matt
>
> On Thu, Aug 25, 2016 at 1:22 PM, Russell Bateman
> <ru...@perfectsearchcorp.com> wrote:
>> Matt,
>>
>> Thank you for replying. It extends AbstractProcessor:
>>
>> public class X12MessageRouter extends AbstractProcessor
>> {
>>    @Override
>>    public void onTrigger( final ProcessContext context, final ProcessSession
>> session ) throws ProcessException
>>    {
>>      FlowFile flowfile = session.get();
>>      ...
>>
>> No, you're right, I don't want to propagate exceptions outside the
>> processor. I wasn't even thinking about that. I really just wanted to test
>> that I'm throwing ProcessorException with the specific message for the
>> specific reason I'm throwing it. Do you have a suggestion based on this?
>>
>> Thanks,
>>
>> Russ
>>
>>
>> On 08/25/2016 11:12 AM, Matt Burgess wrote:
>>> Does your processor extend AbstractProcessor or
>>> AbstractSessionFactoryProcessor? If the former, then all throwables
>>> get caught by the onTrigger method:
>>>
>>> https://github.com/apache/nifi/blob/master/nifi-api/src/main/java/org/apache/nifi/processor/AbstractProcessor.java
>>>
>>> Are you sure you want such exceptions to propagate out of the
>>> processor? Usually you would route a flow file to some failure or
>>> retry relationship, or rollback the session (which is what
>>> AbstractProcessor does). This keeps the integrity of the framework
>>> rather than an exception escaping into the wild.
>>>
>>> Regards,
>>> Matt
>>>
>>> On Thu, Aug 25, 2016 at 12:51 PM, Russell Bateman
>>> <ru...@perfectsearchcorp.com> wrote:
>>>>   From my custom processor, I'm throwing a ProcessException that never
>>>> reaches
>>>> my catch in the JUnit test. I already have several other JUnit tests
>>>> working
>>>> on this processor; this is the remaining wiggle I want to test.
>>>>
>>>> I might be blind here, but I can't see what's wrong. Any comment will be
>>>> useful.
>>>>
>>>> Thanks,
>>>>
>>>> Russ
>>>>
>>>> Here's the tail-end of my processor'sonTrigger() method:
>>>>
>>>>       ...
>>>>
>>>>       try
>>>>       {
>>>>         X12Simple x12 = ( X12Simple ) parser.parse( is.get() );
>>>>         ...
>>>>
>>>>         session.transfer( newFlowfile, resultingRelationship );
>>>>       }
>>>>       catch( FormatException e ) *// this exception is caught--was thrown
>>>> in
>>>> X12 parser as expected!*
>>>>       {
>>>>         session.remove( newFlowfile );
>>>> *      throw new ProcessException( e + " (the content is unparsable as an
>>>> X12 message)" );*
>>>>       }
>>>>       catch( IOException e )
>>>>       {
>>>>         session.remove( newFlowfile );
>>>>         throw new ProcessException( e );
>>>>       }
>>>>     }
>>>>     finally
>>>>     {
>>>>       session.transfer( flowfile, ORIGINAL );
>>>>     }
>>>> }
>>>>
>>>>
>>>> And here's the JUnit test case for now:
>>>>
>>>> @Test
>>>> public void testOnTriggerCompleteCrap()
>>>> {
>>>>     TestRunner runner = TestRunners.newTestRunner( new X12MessageRouter()
>>>> );
>>>>
>>>>     final int         ONE     = 1;
>>>>     final InputStream MESSAGE = new ByteArrayInputStream( _CRAP.getBytes()
>>>> );
>>>>
>>>>     Map< String, String > flowFileAttributes = new HashMap<>();
>>>>     flowFileAttributes.put( "testname", "X12 Message Router Unit Test" );
>>>>
>>>>     runner.setValidateExpressionUsage( false );
>>>>     runner.enqueue( MESSAGE, flowFileAttributes );
>>>>
>>>>     try
>>>>     {
>>>> *runner.run( ONE ); **// (exception will happen under here)*
>>>>       runner.assertQueueEmpty();
>>>>       List< MockFlowFile > results = runner.getFlowFilesForRelationship(
>>>> X12MessageRouter.NONE );
>>>>     }
>>>>     catch( ProcessException e )
>>>>     {
>>>>       int x = 9; *// (never caught at breakpoint set here)*
>>>>     }
>>>> }
>>>>


Re: Unable to catch ProcessException error in JUnit test code

Posted by Matt Burgess <ma...@gmail.com>.
Russ,

You can call runner.getLogger() which gives you a MockComponentLog:
https://github.com/apache/nifi/blob/master/nifi-mock/src/main/java/org/apache/nifi/util/MockComponentLog.java.
From that you can get your messages and check if you logged the
specific one(s) you care about.

Regards,
Matt

On Thu, Aug 25, 2016 at 1:22 PM, Russell Bateman
<ru...@perfectsearchcorp.com> wrote:
> Matt,
>
> Thank you for replying. It extends AbstractProcessor:
>
> public class X12MessageRouter extends AbstractProcessor
> {
>   @Override
>   public void onTrigger( final ProcessContext context, final ProcessSession
> session ) throws ProcessException
>   {
>     FlowFile flowfile = session.get();
>     ...
>
> No, you're right, I don't want to propagate exceptions outside the
> processor. I wasn't even thinking about that. I really just wanted to test
> that I'm throwing ProcessorException with the specific message for the
> specific reason I'm throwing it. Do you have a suggestion based on this?
>
> Thanks,
>
> Russ
>
>
> On 08/25/2016 11:12 AM, Matt Burgess wrote:
>>
>> Does your processor extend AbstractProcessor or
>> AbstractSessionFactoryProcessor? If the former, then all throwables
>> get caught by the onTrigger method:
>>
>> https://github.com/apache/nifi/blob/master/nifi-api/src/main/java/org/apache/nifi/processor/AbstractProcessor.java
>>
>> Are you sure you want such exceptions to propagate out of the
>> processor? Usually you would route a flow file to some failure or
>> retry relationship, or rollback the session (which is what
>> AbstractProcessor does). This keeps the integrity of the framework
>> rather than an exception escaping into the wild.
>>
>> Regards,
>> Matt
>>
>> On Thu, Aug 25, 2016 at 12:51 PM, Russell Bateman
>> <ru...@perfectsearchcorp.com> wrote:
>>>
>>>  From my custom processor, I'm throwing a ProcessException that never
>>> reaches
>>> my catch in the JUnit test. I already have several other JUnit tests
>>> working
>>> on this processor; this is the remaining wiggle I want to test.
>>>
>>> I might be blind here, but I can't see what's wrong. Any comment will be
>>> useful.
>>>
>>> Thanks,
>>>
>>> Russ
>>>
>>> Here's the tail-end of my processor'sonTrigger() method:
>>>
>>>      ...
>>>
>>>      try
>>>      {
>>>        X12Simple x12 = ( X12Simple ) parser.parse( is.get() );
>>>        ...
>>>
>>>        session.transfer( newFlowfile, resultingRelationship );
>>>      }
>>>      catch( FormatException e ) *// this exception is caught--was thrown
>>> in
>>> X12 parser as expected!*
>>>      {
>>>        session.remove( newFlowfile );
>>> *      throw new ProcessException( e + " (the content is unparsable as an
>>> X12 message)" );*
>>>      }
>>>      catch( IOException e )
>>>      {
>>>        session.remove( newFlowfile );
>>>        throw new ProcessException( e );
>>>      }
>>>    }
>>>    finally
>>>    {
>>>      session.transfer( flowfile, ORIGINAL );
>>>    }
>>> }
>>>
>>>
>>> And here's the JUnit test case for now:
>>>
>>> @Test
>>> public void testOnTriggerCompleteCrap()
>>> {
>>>    TestRunner runner = TestRunners.newTestRunner( new X12MessageRouter()
>>> );
>>>
>>>    final int         ONE     = 1;
>>>    final InputStream MESSAGE = new ByteArrayInputStream( _CRAP.getBytes()
>>> );
>>>
>>>    Map< String, String > flowFileAttributes = new HashMap<>();
>>>    flowFileAttributes.put( "testname", "X12 Message Router Unit Test" );
>>>
>>>    runner.setValidateExpressionUsage( false );
>>>    runner.enqueue( MESSAGE, flowFileAttributes );
>>>
>>>    try
>>>    {
>>> *runner.run( ONE ); **// (exception will happen under here)*
>>>      runner.assertQueueEmpty();
>>>      List< MockFlowFile > results = runner.getFlowFilesForRelationship(
>>> X12MessageRouter.NONE );
>>>    }
>>>    catch( ProcessException e )
>>>    {
>>>      int x = 9; *// (never caught at breakpoint set here)*
>>>    }
>>> }
>>>
>

Re: Unable to catch ProcessException error in JUnit test code

Posted by Russell Bateman <ru...@perfectsearchcorp.com>.
Matt,

Thank you for replying. It extends AbstractProcessor:

public class X12MessageRouter extends AbstractProcessor
{
   @Override
   public void onTrigger( final ProcessContext context, final 
ProcessSession session ) throws ProcessException
   {
     FlowFile flowfile = session.get();
     ...

No, you're right, I don't want to propagate exceptions outside the 
processor. I wasn't even thinking about that. I really just wanted to 
test that I'm throwing ProcessorException with the specific message for 
the specific reason I'm throwing it. Do you have a suggestion based on this?

Thanks,

Russ

On 08/25/2016 11:12 AM, Matt Burgess wrote:
> Does your processor extend AbstractProcessor or
> AbstractSessionFactoryProcessor? If the former, then all throwables
> get caught by the onTrigger method:
> https://github.com/apache/nifi/blob/master/nifi-api/src/main/java/org/apache/nifi/processor/AbstractProcessor.java
>
> Are you sure you want such exceptions to propagate out of the
> processor? Usually you would route a flow file to some failure or
> retry relationship, or rollback the session (which is what
> AbstractProcessor does). This keeps the integrity of the framework
> rather than an exception escaping into the wild.
>
> Regards,
> Matt
>
> On Thu, Aug 25, 2016 at 12:51 PM, Russell Bateman
> <ru...@perfectsearchcorp.com> wrote:
>>  From my custom processor, I'm throwing a ProcessException that never reaches
>> my catch in the JUnit test. I already have several other JUnit tests working
>> on this processor; this is the remaining wiggle I want to test.
>>
>> I might be blind here, but I can't see what's wrong. Any comment will be
>> useful.
>>
>> Thanks,
>>
>> Russ
>>
>> Here's the tail-end of my processor'sonTrigger() method:
>>
>>      ...
>>
>>      try
>>      {
>>        X12Simple x12 = ( X12Simple ) parser.parse( is.get() );
>>        ...
>>
>>        session.transfer( newFlowfile, resultingRelationship );
>>      }
>>      catch( FormatException e ) *// this exception is caught--was thrown in
>> X12 parser as expected!*
>>      {
>>        session.remove( newFlowfile );
>> *      throw new ProcessException( e + " (the content is unparsable as an
>> X12 message)" );*
>>      }
>>      catch( IOException e )
>>      {
>>        session.remove( newFlowfile );
>>        throw new ProcessException( e );
>>      }
>>    }
>>    finally
>>    {
>>      session.transfer( flowfile, ORIGINAL );
>>    }
>> }
>>
>>
>> And here's the JUnit test case for now:
>>
>> @Test
>> public void testOnTriggerCompleteCrap()
>> {
>>    TestRunner runner = TestRunners.newTestRunner( new X12MessageRouter() );
>>
>>    final int         ONE     = 1;
>>    final InputStream MESSAGE = new ByteArrayInputStream( _CRAP.getBytes() );
>>
>>    Map< String, String > flowFileAttributes = new HashMap<>();
>>    flowFileAttributes.put( "testname", "X12 Message Router Unit Test" );
>>
>>    runner.setValidateExpressionUsage( false );
>>    runner.enqueue( MESSAGE, flowFileAttributes );
>>
>>    try
>>    {
>> *runner.run( ONE ); **// (exception will happen under here)*
>>      runner.assertQueueEmpty();
>>      List< MockFlowFile > results = runner.getFlowFilesForRelationship(
>> X12MessageRouter.NONE );
>>    }
>>    catch( ProcessException e )
>>    {
>>      int x = 9; *// (never caught at breakpoint set here)*
>>    }
>> }
>>


Re: Unable to catch ProcessException error in JUnit test code

Posted by Matt Burgess <ma...@gmail.com>.
Does your processor extend AbstractProcessor or
AbstractSessionFactoryProcessor? If the former, then all throwables
get caught by the onTrigger method:
https://github.com/apache/nifi/blob/master/nifi-api/src/main/java/org/apache/nifi/processor/AbstractProcessor.java

Are you sure you want such exceptions to propagate out of the
processor? Usually you would route a flow file to some failure or
retry relationship, or rollback the session (which is what
AbstractProcessor does). This keeps the integrity of the framework
rather than an exception escaping into the wild.

Regards,
Matt

On Thu, Aug 25, 2016 at 12:51 PM, Russell Bateman
<ru...@perfectsearchcorp.com> wrote:
> From my custom processor, I'm throwing a ProcessException that never reaches
> my catch in the JUnit test. I already have several other JUnit tests working
> on this processor; this is the remaining wiggle I want to test.
>
> I might be blind here, but I can't see what's wrong. Any comment will be
> useful.
>
> Thanks,
>
> Russ
>
> Here's the tail-end of my processor'sonTrigger() method:
>
>     ...
>
>     try
>     {
>       X12Simple x12 = ( X12Simple ) parser.parse( is.get() );
>       ...
>
>       session.transfer( newFlowfile, resultingRelationship );
>     }
>     catch( FormatException e ) *// this exception is caught--was thrown in
> X12 parser as expected!*
>     {
>       session.remove( newFlowfile );
> *      throw new ProcessException( e + " (the content is unparsable as an
> X12 message)" );*
>     }
>     catch( IOException e )
>     {
>       session.remove( newFlowfile );
>       throw new ProcessException( e );
>     }
>   }
>   finally
>   {
>     session.transfer( flowfile, ORIGINAL );
>   }
> }
>
>
> And here's the JUnit test case for now:
>
> @Test
> public void testOnTriggerCompleteCrap()
> {
>   TestRunner runner = TestRunners.newTestRunner( new X12MessageRouter() );
>
>   final int         ONE     = 1;
>   final InputStream MESSAGE = new ByteArrayInputStream( _CRAP.getBytes() );
>
>   Map< String, String > flowFileAttributes = new HashMap<>();
>   flowFileAttributes.put( "testname", "X12 Message Router Unit Test" );
>
>   runner.setValidateExpressionUsage( false );
>   runner.enqueue( MESSAGE, flowFileAttributes );
>
>   try
>   {
> *runner.run( ONE ); **// (exception will happen under here)*
>     runner.assertQueueEmpty();
>     List< MockFlowFile > results = runner.getFlowFilesForRelationship(
> X12MessageRouter.NONE );
>   }
>   catch( ProcessException e )
>   {
>     int x = 9; *// (never caught at breakpoint set here)*
>   }
> }
>