blob: 54378bb34cedfe187b8e3ec698b1ea13097f047b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
class RaiseErrorMatcher
FAILURE_MESSAGE_FOR_EXCEPTION = {}.compare_by_identity
attr_writer :block
def initialize(exception, message, &block)
@exception = exception
@message = message
@block = block
@actual = nil
end
# This #matches? method is unusual because it doesn't always return a boolean but instead
# re-raises the original exception if proc.call raises an exception and #matching_exception? is false.
# The reasoning is the original exception class matters and we don't want to change it by raising another exception,
# so instead we attach the #failure_message and extract it in ExceptionState#message.
def matches?(proc)
@result = proc.call
return false
rescue Object => actual
@actual = actual
if matching_exception?(actual)
# The block has its own expectations and will throw an exception if it fails
@block[actual] if @block
return true
else
FAILURE_MESSAGE_FOR_EXCEPTION[actual] = failure_message
raise actual
end
end
def matching_class?(exc)
@exception === exc
end
def matching_message?(exc)
case @message
when String
@message == exc.message
when Regexp
@message =~ exc.message
else
true
end
end
def matching_exception?(exc)
matching_class?(exc) and matching_message?(exc)
end
def exception_class_and_message(exception_class, message)
if message
"#{exception_class} (#{message})"
else
"#{exception_class}"
end
end
def format_expected_exception
exception_class_and_message(@exception, @message)
end
def format_exception(exception)
exception_class_and_message(exception.class, exception.message)
end
def failure_message
message = ["Expected #{format_expected_exception}"]
if @actual
message << "but got: #{format_exception(@actual)}"
else
message << "but no exception was raised (#{MSpec.format(@result)} was returned)"
end
message
end
def negative_failure_message
message = ["Expected to not get #{format_expected_exception}", ""]
unless @actual.class == @exception
message[1] = "but got: #{format_exception(@actual)}"
end
message
end
end
module MSpecMatchers
private def raise_error(exception = Exception, message = nil, &block)
RaiseErrorMatcher.new(exception, message, &block)
end
end
|