I am trying my first features with Behat and I am facing the problem I don't know how to implement expected exceptions.
I found the issue https://github.com/Behat/Behat/issues/140 and robocoder is talking about one possible way, which is used by Behat, too. But it seems that they aren't really handling exceptions.
My point is to achieve forced exception handling. I don't want any construct catching all exceptions and forget them.
One possible way would be:
When <player> transfers <transfer> from his account it should fail with <error>
Implementation
try {
...
} catch (\Exception $ex) {
assertEquals($error, $ex->getMessage());
}
I don't like the scenario description. I want to use the then keyword, e.g.
When <player> transfers <transfer> from his account
Then it should fail with error <error>
This description has the disadvantage I need two methods:
method1($arg1, $arg2) {
// Test the transfer
}
method2($arg1, $arg2) {
// Check if the exception is the right one
}
To be able to check in method2 the exception needs to be stored.
The only possible way I see is to use a try/catch and store it to a variable.
Someone else would catch it and do nothing with it. Nobody will notice, when running the tests.
How can I prevent that exceptions are discarded?
Has anybody else a similar scenario implemented?
Thanks for any hints.
EDIT:
Behat context:
playerTransfer($player, $amount) {
$player->transfer($amount);
}
Method from entity class:
transfer($amount) {
if ($this->getWealth() < $amount) {
throw NotEnoughMoney();
}
...
}
Always try to catch method outcome to context class field, for example:
//inside Behat context class method
try {
$this->outcome = $func();
}
catch(\Exception $ex) {
$this->outcome = $ex;
}
Now when expecting exception at next step just check if $this->outcome is instanceof desired exception with message/code.
I think the problem is in your implementation. Do you check if transfer is successful in "When transfers from his account" ? Do you need to check it ?
Failure test:
When <player> transfers <transfer> from his account
Then I should see error <error>
Successful step:
When <player> transfers <transfer> from his account
Then I should see "transfer successful"
Here's how I successfully did it in a project of mine where I had to repeat a few steps till the condition held true:
/**
* #Given /^I execute some conditions$/
*/
public function executeConditions()
{
$flag = 1;
do {
try {
<steps to be executed till the condition holds true>
$flag=1;
} catch (\Exception $ex) {
$flag = 0;
}
}while ($flag>0);
}
Related
I have following code
IAsyncOperation<bool> trythiswork()
{
bool contentFound{ false };
try
{
auto result = co_await someAsyncFunc();
winrt::check_bool(result)
if (result)
{
contentFound = true;
}
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
}
co_return contentFound;
}
When the result is false, it fails and throws but catch goes to fail fast and program terminates. How does log function terminate the program? Isn't it supposed to only log the exception? I assumed that I am handling this exception so program won't crash but it is crashing.
So how to throw and catch so that program does not terminate? I do want to throw. And also catch and preferably log the exception as well.
Thanks
The issue can be reproduced using the following code:
IAsyncOperation<bool> someAsyncFunc() { co_return false; }
IAsyncOperation<bool> trythiswork()
{
auto contentFound { false };
try
{
auto result = co_await someAsyncFunc();
winrt::check_bool(result);
// throw std::bad_alloc {};
contentFound = true;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
}
co_return contentFound;
}
int main()
{
init_apartment();
auto result = trythiswork().get();
}
As it turns out, everything works as advertised, even if not as intended. When running the code with a debugger attached you will see the following debug output:
The exception %s (0x [trythiswork]
Not very helpful, but it shows that logging itself works. This is followed up by something like
FailFast(1) tid(b230) 8007023E {Application Error}
causing the process to terminate. The WIL only recognizes exceptions of type std::exception, wil::ResultException, and Platform::Exception^. When it handles an unrecognized exception type it will terminate the process by default. This can be verified by commenting out the call to check_bool and instead throwing a standard exception (such as std::bad_alloc). This produces a program that will log exception details, but continue to execute.
The behavior can be customized by registering a callback for custom exception types, giving clients control over translating between custom exception types and HRESULT values. This is useful in cases where WIL needs to interoperate with external library code that uses its own exception types.
For C++/WinRT exception types (based on hresult_error) the WIL already provides error handling helpers that can be enabled (see Integrating with C++/WinRT). To opt into this all you need to do is to #include <wil/cppwinrt.h> before any C++/WinRT headers. When using precompiled headers that's where the #include directive should go.
With that change, the program now works as desired: It logs exception information for exceptions that originate from C++/WinRT, and continues to execute after the exception has been handled.
In Python, I would do this:
try:
some_func()
except Exception:
handle_error()
else:
print("some_func was successful")
do_something_else() # exceptions not handled here, deliberately
finally:
print("this will be printed in any case")
I find this very elegant to read; the else block will only be reached if no exception was thrown.
How does one do this in Kotlin? Am I supposed to declare a local variable and check that below the block?
try {
some_func()
// do_something_else() cannot be put here, because I don't want exceptions
// to be handled the same as for the statement above.
} catch (e: Exception) {
handle_error()
} finally {
// reached in any case
}
// how to handle 'else' elegantly?
I found Kotlin docs | Migrating from Python | Exceptions, but this does not cover the else block functionality as found in Python.
Another way to use runCatching is to use the Result's extension functions
runCatching {
someFunc()
}.onFailure { error ->
handleError(error)
}.onSuccess { someFuncReturnValue ->
handleSuccess(someFuncReturnValue)
}.getOrDefault(defaultValue)
.also { finalValue ->
doFinalStuff(finalValue)
}
Take a look at the docs for Result: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html
If you do not care about the default value, for example, you want just to hide the loading you could use this:
runCatching {
show_loading(true) //show loading indicator
some_func() //this could throw an exception
}.onFailure {
handle_error(it.message)
}.getOrNull().run {
show_loading(false) //hide loading indicator regardless error or success
}
Depending on database result, some properties of my object may be populated or not.
Lets say I have a task object and if there is a message for it, so it has the $message property populated:
if($task->message === null)
throw new ErrorException('what the ...');
The problem is, whenever I want to check if this property is populated (accessing it), it throws an Getting unknown property exception and the execution terminates.
I think you can try with isset
if (isset($task->message )) {
// your code for is setted
} else {
// your code for not setted
}
Try-catch block also works:
use yii\base\Exception;
[...]
try {
echo $task->message;
} catch (Exception $e) {
// stuff
}
I have a service method which does some operation inside a transaction.
public User method1() {
// some code...
Vehicle.withTransaction { status ->
// some collection loop
// some other delete
vehicle.delete(failOnError:true)
}
if (checkSomething outside transaction) {
return throw some user defined exception
}
return user
}
If there is a runtime exception we dont have to catch that exception and the transaction will be rolled back automatically. But how to determine that transaction rolled back due to some exception and I want to throw some user friendly error message. delete() call also wont return anything.
If I add try/catch block inside the transaction by catching the Exception (super class) it is not getting into that exception block. But i was expecting it to go into that block and throw user friendly exception.
EDIT 1: Is it a good idea to add try/catch arround withTransaction
Any idea how to solver this?? Thanks in advance.
If I understand you question correctly, you want to know how to catch an exception, determine what the exception is, and return a message to the user. There are a few ways to do this. I will show you how I do it.
Before I get to the code there are a few things I might suggest. First, you don't need to explicitly declare the transaction in a service (I'm using v2.2.5). Services are transactional by default (not a big deal).
Second, the transaction will automatically roll back if any exception occurs while executing the service method.
Third, I would recommend removing failOnError:true from save() (I don't think it works on delete()... I may be wrong?). I find it is easier to run validate() or save() in the service then return the model instance to the controller where the objects errors can be used in a flash message.
The following is a sample of how I like to handle exceptions and saves using a service method and try/catch in the controller:
class FooService {
def saveFoo(Foo fooInstance) {
return fooInstance.save()
}
def anotherSaveFoo(Foo fooInstance) {
if(fooInstance.validate()){
fooInstance.save()
}else{
do something else or
throw new CustomException()
}
return fooInstance
}
}
class FooController {
def save = {
def newFoo = new Foo(params)
try{
returnedFoo = fooService.saveFoo(newFoo)
}catch(CustomException | Exception e){
flash.warning = [message(code: 'foo.validation.error.message',
args: [org.apache.commons.lang.exception.ExceptionUtils.getRootCauseMessage(e)],
default: "The foo changes did not pass validation.<br/>{0}")]
redirect('to where ever you need to go')
return
}
if(returnedFoo.hasErrors()){
def fooErrors = returnedFoo.errors.getAllErrors()
flash.warning = [message(code: 'foo.validation.error.message',
args: [fooErrors],
default: "The foo changes did not pass validation.<br/>${fooErrors}")]
redirect('to where ever you need to go')
return
}else {
flash.success = [message(code: 'foo.saved.successfully.message',
default: "The foo was saved successfully")]
redirect('to where ever you need to go')
}
}
}
Hope this helps, or gets some other input from more experienced Grails developers.
Here are a few other ways I've found to get exception info to pass along to your user:
request.exception.cause
request.exception.cause.message
response.status
A few links to other relevant questions that may help:
Exception handling in Grails controllers
Exception handling in Grails controllers with ExceptionMapper in Grails 2.2.4 best practice
https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html
I have an if condition which checks for value and the it throws new NumberFormatException
Is there any other way to code this
if (foo)
{
throw new NumberFormatException
}
// ..
catch (NumberFormatException exc)
{
// some msg...
}
If you are doing something such as this:
try
{
// some stuff
if (foo)
{
throw new NumberFormatException();
}
}
catch (NumberFormatException exc)
{
do something;
}
Then sure, you could avoid the exception completely and do the 'do something' part inside the conditional block.
If your aim is to avoid to throw a new exception:
if(foo)
{
//some msg...
} else
{
//do something else
}
Don't throw exceptions if you can handle them in another, more elegant manner. Exceptions are expensive and should only be used for cases where there is something going on beyond your control (e.g. a database server is not responding).
If you are trying to ensure that a value is set, and formatted correctly, you should try to handle failure of these conditions in a more graceful manner. For example...
if(myObject.value != null && Checkformat(myObject.Value)
{
// good to go
}
else
{
// not a good place to be. Prompt the user rather than raise an exception?
}
In Java, you can try parsing a string with regular expressions before trying to convert it to a number.
If you're trying to catch your own exception (why???) you could do this:
try { if (foo) throw new NumberFormatException(); }
catch(NumberFormatexception) {/* ... */}
if you are trying to replace the throwing of an exception with some other error handling mechanism your only option is to return or set an error code - the problem is that you then have to go and ensure it is checked elsewhere.
the exception is best.
If you know the flow that will cause you to throw a NumberFormatException, code to handle that case. You shouldn't use Exception hierarchies as a program flow mechanism.