I am trying to test a java.sql.SQLException handler which unwraps the exceptions like below. However I'm not sure how I would throw this exception in a test.
(-> e
(.getNextException)
(.getMessage)
(.startsWith "ERROR: duplicate key value"))
current mock (.getNextException) returns nil on this:
(throw (SQLException. "ERROR: duplicate key value"))
You want:
(throw (doto (SQLException. "Top-level exception")
(.setNextException (SQLException. "ERROR: duplicate key value"))))
Related
I've been searching for some time now, and I'm sure I've missed it, is there any documentation that states what should be thrown when a value is incorrect/blank?
For example, Python has ValueError and the documentation clearly states when to use it.
I have the following method:
proc getJobinfo {question} {
puts -nonewline "$question: "
flush stdout
gets stdin answer
set cleanedanswer [string trim [string totitle $answer]]
if {$cleanedanswer eq ""} {
# What error should be thrown?
}
return $cleanedanswer
}
I've searched throw, error, and catch, but couldn't find it.
Tcl doesn't have a pre-defined hierarchy of exceptions. The throw command takes 2 arguments: type is a list of words; and message is an error message for humans.
You could do something like
proc getJobinfo {question} {
...
if {$cleanedanswer eq ""} {
throw {Value Empty} "Please provide a suitable answer."
} elseif {[string length $cleanedanswer] < 5} {
throw {Value Invalid} "Your answer is too short."
} else ...
return $cleanedanswer
}
If you want to trap that error:
try {
set answer [getJobinfo "What is the answer to this question"]
} trap {Value *} msg {
puts "Value Error: $msg"
}
throw and try interact via the type words of the throw call. We throw "Value Empty" or "Value Invalid". In the trap, we match Value exactly, but we won't match * exactly. In hindsight the * should not be there.
The try manpage is not super clear at first read:
trap pattern variableList script
This clause matches if the evaluation of body resulted in an error and the prefix of the -errorcode from the interpreter's status dictionary is equal to the pattern. The number of prefix words taken from the -errorcode is equal to the list-length of pattern, and inter-word spaces are normalized in both the -errorcode and pattern before comparison.
pattern is not a pattern in the regexp or string match sense: it's a list of words that is matched one-by-one with the list of words thrown in the try body.
The try can be implemented with multiple traps to have cascading "catches":
try {
set answer [getJobinfo "What is the answer to this question"]
} trap {Value Empty} msg {
do something specific here
} trap {Value Invalid} msg {
do something specific here
} trap {Value} msg {
do something general for some other "throw {Value anything} msg"
} on error e {
this can be default catch-all for any other error
} finally {
any cleanup code goes here
}
I'm trying to use Plug.Test to test error handling implemented with Plug.ErrorHandler -- with assert conn.status == 406 and alike.
I have the defp handle_errors (containing a single send_resp statement) and it seems to be called, however, my tests fail with the same exception still (as if handle_errors has no effect).
A reference to a sample advanced Plug (not Phoenix) app will also be appreciated.
Try something like this (not tested):
defmodule NotAcceptableError do
defexception plug_status: 406, message: "not_acceptable"
end
defmodule Router do
use Plug.Router
use Plug.ErrorHandler
plug :match
plug :dispatch
get "/hello" do
raise NotAcceptableError
send_resp(conn, 200, "world")
end
def handle_errors(conn, %{kind: _kind, reason: reason, stack: _stack}) do
send_resp(conn, conn.status, reason.message)
end
end
test "error" do
conn = conn(:get, "/hello")
assert_raise Plug.Conn.WrapperError, "** (NotAcceptableError not_acceptable)", fn ->
Router.call(conn, [])
end
assert_received {:plug_conn, :sent}
assert {406, _headers, "not_acceptable"} = sent_resp(conn)
end
Use assert_error_sent/2 to assert that you raised an error and it was wrapped and sent with a particular status. Match against its {status, headers, body} return value to assert the rest of the HTTP response met your expectations.
response = assert_error_sent 404, fn ->
get(build_conn(), "/users/not-found")
end
assert {404, [_h | _t], "Page not found"} = response
#!/usr/bin/tclsh
proc test {} {
aaa
}
test
When I run this script I get error message:
invalid command name "aaa"
while executing
"aaa"
(procedure "test" line 2)
invoked from within
"test"
(file "./a.tcl" line 7)
If I run test command in catch I get only first line of error message.
#!/usr/bin/tclsh
proc test {} {
aaa
}
catch test msg
puts $msg
This prints:
invalid command name "aaa"
Is it possible to get full error message (file, line, procedure) in catch command? My program has many files and by getting just one line of error message it is difficult to find from where is it.
The short answer is to look at the value of errorInfo which will contain the stack trace.
The more complete answer is to look at the catch and the return manual pages and make use of the -optionsVarName parameter to the catch statement to collect the more detailed information provided. The return manual page gives some information on using this. But a rough example from an interactive session:
% proc a {} { catch {funky} err detail; return $detail }
% a
-code 1 -level 0 -errorstack {INNER {invokeStk1 funky} CALL a} -errorcode NONE -errorinfo {invalid command name "funky"
while executing
"funky"} -errorline 1
%
The detail variable is a dictionary, so use dict get $detail -errorinfo to get that particular item.
I wanna do a test on a method call similar to:
call_to_method_1 param1
this method can raise for example:
raise msg1 if ...
raise msg2 if ...
My question is How to test exception with its msg1, msg2 exception messages wtih RSpec.
describe SomeClass do
let(:some_object) { described_class.new }
it 'should raise an exception' do
some_object.some_method('param').should raise_error(ExceptionClass, "exception_message")
end
end
if you raise "message" then the ExceptionClass will be instance of RuntimeClass.
IMO it's better to raise specific type of exception instead of relying on message though.
I have this kind of a grammar,
locationPath returns [CustomParser xpathParser]
:^(LOCATION_PATH relativeLocationPath {**Want to throw a exception if this condition matches**})
|^(LOCATION_PATH absoluteLocationPath {$xpathParser=$absoluteLocationPath.xpathParser;})
;
What is the way to do it? I tried with this one
locationPath returns [CustomParser xpathParser]
:^(LOCATION_PATH relativeLocationPath {throw new Exception})
|^(LOCATION_PATH absoluteLocationPath {$xpathParser=$absoluteLocationPath.xpathParser;})
But with this one the generated code gives compile Error. Because that method loactionapth doesn't have throws clues at method signature.
Only one way to do this: throw an unchecked exception:
locationPath returns [CustomParser xpathParser]
: ^(LOCATION_PATH relativeLocationPath) {throw new RuntimeException("No way!");}
| ^(LOCATION_PATH absoluteLocationPath {$xpathParser=$absoluteLocationPath.xpathParser;})
;
If the compiler still complains (I can't remember, and I'm not able to test right now), add an if(true) in front of it:
locationPath returns [CustomParser xpathParser]
: ^(LOCATION_PATH relativeLocationPath) {if(true) throw new RuntimeException("No way!");}
| ^(LOCATION_PATH absoluteLocationPath {$xpathParser=$absoluteLocationPath.xpathParser;})
;