I'm new to Mockito and want to use it in unit tests.
What I don't like is mocks created with Mockito.mock(Class<T>) return default values (like null) for methods that have no behavior explicitly defined. Instead, I want them to throw an exception in this case so I know that I need to add this definition.
I tried the following:
SomeType m = mock( SomeType.class, new ThrowsException( new SomeRuntimeException( ... ) ) );
when( m.a() ).thenReturn( ... );
m.a(); // ok
m.b(); // throws exception
But that doesn't work because the exception is thrown already during the call to when().
Is there some other way to achieve this?
Replace
when( m.a() ).thenReturn( ... );
with
doReturn( ... ).when(m).a();
Related
I have simplified my use case with an Order/items example.
An order has some items.
Every item is controlled => An AvailabilityException can be thrown from "controlItem".
After the exception is thrown, item is marked as Ok and next item is handled.
onException(AvailabilityException.class)
.onExceptionOccurred(ItemProcessor)
.handled(true)
.bean(service, "markAsOk");
from(startQueue)
.split(simple("${body.items}"))
.to(direct:controlItem")
.end()
.to(successQueue);
from("direct:controlItem")
.bean(service, "controlItem");
Now I have another case :
When an unexpected exception (NullPointerException, ...) is thrown I would like to stop the process. We don't handle next items and order is redirected to an error queue.
How can I do that ?
You can use doTry and doCatch
from(startQueue)
.doTry()
.split(simple("${body.items}"))
.to(direct:controlItem")
.end()
.to(successQueue);
.doCatch(AvailabilityException.class)
....
....
.handled(true)
.doCatch(RunTimeException.class)
....
....
.handled(false)
.stop() // stop the execution
.doFinally() //optional
Instead of stop() you can write a processor there and use exchange.getContext().stop();
You can as well add another onException for RunTimeExceptions and stop the route.
Another possible way is to use the property ROUTE_STOP . You can set this property to true in a processor on exception.
exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE);
I have a simple query on a table which queries with the primary key.
dslContext.select(XXX.NAME)
.from(XXX)
.where(
XXX.ID.eq(id)
.and(XXX.LEVEL.eq(2))
.and(XXX.NAME.isNotNull())
)
.fetchOne().into(String.class);
In my case for a particular id, the query results in a empty set. But jooq seems to throw a NPE. When I further investigated, fetchOne() calls CursorImpl.fetchOne(). This checks the size of the result and if it is not 1, it returns null. I have a chained into(String.class) which gets called on this null value and hence resulting in NPE.
I don't want to call fetch() and iterate over the results/get the first element of the list.
Is there an alternative way of writing the query such that it will throw a org.jooq.exception.NoDataFoundException if there is no data?
Why a NullPointerException is being thrown
Technically, jOOQ doesn't throw a NullPointerException. Your calling into(Class) on a potentially null record does, as documented also in the Javadoc of ResultQuery.fetchOne()
Returns:
The resulting record or null if the query returns no records.
Throwing a NoDataFoundException.
You could use fetchOptional() and then use orElseThrow():
String string =
dslContext.select(XXX.NAME)
.from(XXX)
.where(
XXX.ID.eq(id)
.and(XXX.LEVEL.eq(2))
.and(XXX.NAME.isNotNull())
)
.fetchOptional()
.orElseThrow(() -> new NoDataFoundException("..."))
.into(String.class);
Note, there's a pending feature request for such a built-in fetch method: https://github.com/jOOQ/jOOQ/issues/5411
In jOOQ 3.10, you will be able to write:
String string =
dslContext.select(XXX.NAME)
.from(XXX)
.where(
XXX.ID.eq(id)
.and(XXX.LEVEL.eq(2))
.and(XXX.NAME.isNotNull())
)
.fetchSingle() // Might throw a NoDataFoundException but never returns null
.into(String.class);
I have the following array
ArrayList<Car> list = new ArrayList<>();
I want to iterate it and throw an exception if it contains a certain value
i.e.
if at least one
list.stream.filter(x -> x.color.equals("Black"));
then I want to stop iteration and throw an exception.
Is there a way?
You could use anyMatch for this:
boolean matched = list.stream().anyMatch(x -> x.color.equals("Black"));
if(matched) throw new SomeException();
Since it does not evaluate the rest of the pipeline if the condition is satisfied for one element when iterating through it, and that it returns false if the stream is empty, I think this is what you are looking for.
Of course, you could do it in a single statement but it may not improve readability depending on the situation:
if(list.stream().anyMatch(x -> x.color.equals("Black"))) {
throw new SomeException();
}
Easiest is:
list.forEach( x -> {
if(x.color.equals("Black")) throw new RuntimeException();
});
I have several custom exception classes that were created "With Message Class". Since I can't directly get a message from them, I want to create a utility method that returns a BAPIRET2 from a given exception based on the values in IF_T100_MESSAGE~T100KEY. However, I can't provide that method with a generic CX_ROOT importing parameter as this class is not message-enabled. I also can't create a generic message-enabled exception class as new classes have to inherit from one of CX_STATIC_CHECK, CX_DYNAMIC_CHECK, or CX_NOCHECK.
How can I then retrieve the message details from an unspecified exception? Should I create a method that receives a CX_ROOT and then does up to three calls to methods with an import typed to each of the three possible subclasses? Or are there better alternatives?
You could prepare a type descriptor of the interface (once):
DATA: lr_t100_descr TYPE REF TO cl_abap_intfdescr.
lr_t100_descr ?= cl_abap_typedescr=>describe_by_name( 'IF_T100_MESSAGE' ).
and then examine each exception as it comes your way:
DATA: lr_t100_exception TYPE REF TO if_t100_message.
IF lr_t100_descr->applies_to( ir_any_exception ) = abap_true.
lr_t100_exception ?= ir_any_exception.
" ...
ENDIF.
You could use the message collector object, so for example
DATA:
excp type ref to CX_ROOT,
bapi_messages type BAPIRETTAB,
message_collector type ref to IF_RECA_MESSAGE_LIST.
FIELD_SYMBOLS:
<bapi_message> TYPE BAPIRET2.
message_collector = cf_reca_message_list=>create( ).
TRY.
" some code which may cause and exception
CATCH cx_root into excp.
message_collector->add_from_exxeption( io_exception = excp).
ENDTRY.
bapi_messages = message_collector->get_list_as_bapiret( ).
LOOP AT bapi_messages ASSIGNING <bapi_message>.
" write out message
ENDLOOP.
It is well worth checking out the message collector object.
For example
http://wiki.scn.sap.com/wiki/display/profile/2007/07/09/Message+Handling+-+Finding+the+Needle+in+the+Haystack
For a logging class I use something like this:
METHOD add_message_exception.
DATA:
lr_type TYPE REF TO cl_abap_typedescr,
lr_class TYPE REF TO cl_abap_classdescr,
lr_intf TYPE REF TO cl_abap_intfdescr,
l_bapiret2 TYPE bapiret2,
lr_msg TYPE REF TO if_t100_message.
CHECK ir_exception IS NOT INITIAL.
l_bapiret2-type = i_type.
"Test for T100KEY interface
cl_abap_classdescr=>describe_by_object_ref(
EXPORTING
p_object_ref = ir_exception
RECEIVING
p_descr_ref = lr_type
EXCEPTIONS
reference_is_initial = 1
OTHERS = 2 ).
TRY.
lr_class ?= lr_type.
IF sy-subrc = 0.
lr_class->get_interface_type(
EXPORTING
p_name = 'IF_T100_MESSAGE'
RECEIVING
p_descr_ref = lr_intf
EXCEPTIONS
interface_not_found = 1
OTHERS = 2 ).
IF sy-subrc = 0.
lr_msg ?= ir_exception. "Cast to interface
l_bapiret2-id = lr_msg->t100key-msgid.
l_bapiret2-number = lr_msg->t100key-msgno.
cl_message_helper=>set_msg_vars_for_if_t100_msg( text = lr_msg ).
l_bapiret2-message_v1 = sy-msgv1.
l_bapiret2-message_v2 = sy-msgv2.
l_bapiret2-message_v3 = sy-msgv3.
l_bapiret2-message_v4 = sy-msgv4.
l_bapiret2-message = me->get_msg(
i_msgid = l_bapiret2-id
i_msgno = l_bapiret2-number ).
ENDIF.
ENDIF.
CATCH cx_root.
"Pokémon exception handling
ENDTRY.
"No T100KEY Interface available
IF lr_msg IS INITIAL.
l_bapiret2-message = ir_exception->if_message~get_text( ).
l_bapiret2-message_v1 = sy-msgv1.
l_bapiret2-message_v2 = sy-msgv2.
l_bapiret2-message_v3 = sy-msgv3.
l_bapiret2-message_v4 = sy-msgv4.
ENDIF.
ENDMETHOD.
Hope this helps as I struggled with the same problem. Maybe there is some adjustment needed, but I think you get the basic idea. This method can handle
I might be missing something, but can't you just use IF_MESSAGE~GET_TEXT which is present on CX_ROOT ?
Otherwise, I would make it the responsibility of the custom exception class to have a method that can return a proper message ( it might rely on the utility method you are planning on ).
I have a many-to-one relationship that users can edit via checkboxes. PK of Foo is ID, and fid contains the id from the checkbox.
I'm checking to see if an element exists with:
Foo ent;
try
{
ent = ctx.Foo.First(f => f.ID == fid);
}
catch (System.InvalidOperationException ioe)
{
ent = new Foo();
}
It seems to me that I should be able to do this without throwing an exception. What would be the best way to do this?
The InvalidOperationException you get has the message:
Sequence contains no matching element
The behaviour of First is that it throws this exception if the element is not found.
You can use FirstOrDefault instead of First and check for null. The null-coalescing operator (??) can be used to make this check.
Foo ent = ctx.Foo.FirstOrDefault(f => f.ID == fid) ?? new Foo();
Note also that there is a similar pair of functions, Single and SingleOrDefault that throw an exception if more than one matching element is found. In your specific case, assuming that the identities should be unique, it might be more appropriate to use SingleOrDefault.