Class: Servactory::TestKit::Rspec::Helpers::ServiceMockBuilder
- Inherits:
-
Object
- Object
- Servactory::TestKit::Rspec::Helpers::ServiceMockBuilder
- Defined in:
- lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb
Overview
Fluent builder for configuring Servactory service mocks in RSpec tests.
## Purpose
ServiceMockBuilder provides a fluent API for stubbing Servactory service calls in tests. It handles both success and failure scenarios, output configuration, input argument matching, and sequential call responses.
## Usage
Basic success mock:
“‘ruby allow_service(MyService)
.succeeds(result: "value")
“‘
Failure mock:
“‘ruby allow_service(MyService)
.fails(type: :base, message: "Error")
“‘
Failure mock with custom exception class:
“‘ruby allow_service(MyService)
.fails(CustomException, type: :base, message: "Error")
“‘
Sequential returns (first call succeeds, second fails):
“‘ruby allow_service(MyService)
.succeeds(count: 1)
.then_succeeds(count: 2)
.then_fails(type: :base, message: "Error")
“‘
With input matching:
“‘ruby allow_service(MyService)
.with(user_id: 123)
.succeeds(user: user)
# Or order doesn’t matter: allow_service(MyService)
.succeeds(user: user)
.with(user_id: 123)
“‘
## Features
-
**Fluent API** - chainable methods for readable test setup
-
Success/Failure - configure expected result type in one method
-
**Exception Handling** - auto-creates exceptions with type, message, meta
-
**Input Matching** - match specific service inputs with ‘.with()`
-
**Sequential Responses** - different results for consecutive calls
-
**Automatic Validation** - validates inputs and outputs against service definition
## Architecture
Works with:
-
ServiceMockConfig - holds mock configuration state
-
MockExecutor - executes the actual RSpec stubbing
-
OutputValidator - validates outputs match service definition
-
InputValidator - validates inputs match service definition
Instance Attribute Summary collapse
-
#config ⇒ ServiceMockConfig
readonly
Current mock configuration.
-
#service_class ⇒ Class
readonly
The Servactory service class being mocked.
Instance Method Summary collapse
-
#fails(exception_class = nil, type: :base, message:, meta: nil) ⇒ ServiceMockBuilder
Configures the mock to return a failure result with exception.
-
#initialize(service_class, method_type:, rspec_context:) ⇒ ServiceMockBuilder
constructor
Creates a new service mock builder.
-
#succeeds(outputs_hash = {}) ⇒ ServiceMockBuilder
Configures the mock to return a successful result with outputs.
-
#then_fails(exception_class = nil, type: :base, message:, meta: nil) ⇒ ServiceMockBuilder
Adds a failure result for sequential call handling.
-
#then_succeeds(outputs_hash = {}) ⇒ ServiceMockBuilder
Adds a successful result for sequential call handling.
-
#with(inputs_hash_or_matcher) ⇒ ServiceMockBuilder
Configures input matching for the mock.
Constructor Details
#initialize(service_class, method_type:, rspec_context:) ⇒ ServiceMockBuilder
Creates a new service mock builder.
91 92 93 94 95 96 97 98 99 100 |
# File 'lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb', line 91 def initialize(service_class, method_type:, rspec_context:) validate_service_class!(service_class) @service_class = service_class @rspec_context = rspec_context @config = ServiceMockConfig.new(service_class:) @config.method_type = method_type @sequential_configs = [] @executed = false end |
Instance Attribute Details
#config ⇒ ServiceMockConfig (readonly)
Returns Current mock configuration.
84 85 86 |
# File 'lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb', line 84 def config @config end |
#service_class ⇒ Class (readonly)
Returns The Servactory service class being mocked.
81 82 83 |
# File 'lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb', line 81 def service_class @service_class end |
Instance Method Details
#fails(exception_class = nil, type: :base, message:, meta: nil) ⇒ ServiceMockBuilder
Configures the mock to return a failure result with exception.
154 155 156 157 158 159 160 161 162 |
# File 'lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb', line 154 def fails(exception_class = nil, type: :base, message:, meta: nil) # rubocop:disable Style/KeywordParametersOrder validate_not_in_sequential_mode!(:fails) validate_result_type_not_switched!(:fails) @config.result_type = :failure @config.exception = build_exception(exception_class, type:, message:, meta:) execute_or_re_execute_mock self end |
#succeeds(outputs_hash = {}) ⇒ ServiceMockBuilder
Configures the mock to return a successful result with outputs.
Outputs are automatically validated against service definition.
123 124 125 126 127 128 129 130 131 132 |
# File 'lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb', line 123 def succeeds(outputs_hash = {}) validate_not_in_sequential_mode!(:succeeds) validate_result_type_not_switched!(:succeeds) validate_outputs!(outputs_hash) @config.result_type = :success @config.outputs = outputs_hash execute_or_re_execute_mock self end |
#then_fails(exception_class = nil, type: :base, message:, meta: nil) ⇒ ServiceMockBuilder
Adds a failure result for sequential call handling.
Use for testing code that calls the same service multiple times.
239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb', line 239 def then_fails(exception_class = nil, type: :base, message:, meta: nil) # rubocop:disable Style/KeywordParametersOrder validate_result_type_defined!(:then_fails) finalize_current_to_sequence @config = ServiceMockConfig.new(service_class:) @config.result_type = :failure @config.exception = build_exception(exception_class, type:, message:, meta:) @config.method_type = @sequential_configs.last&.method_type || :call execute_sequential_mock self end |
#then_succeeds(outputs_hash = {}) ⇒ ServiceMockBuilder
Adds a successful result for sequential call handling.
Use for testing code that calls the same service multiple times. Outputs are automatically validated against service definition.
210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb', line 210 def then_succeeds(outputs_hash = {}) validate_result_type_defined!(:then_succeeds) validate_outputs!(outputs_hash) finalize_current_to_sequence @config = ServiceMockConfig.new(service_class:) @config.result_type = :success @config.outputs = outputs_hash @config.method_type = @sequential_configs.last&.method_type || :call execute_sequential_mock self end |
#with(inputs_hash_or_matcher) ⇒ ServiceMockBuilder
Configures input matching for the mock.
Can be called at any position in the chain (before/after succeeds/fails, or after then_* methods). Applies to the entire mock chain.
Inputs are automatically validated against service definition.
184 185 186 187 188 189 |
# File 'lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb', line 184 def with(inputs_hash_or_matcher) validate_inputs!(inputs_hash_or_matcher) @config.argument_matcher = inputs_hash_or_matcher re_execute_mock if @executed self end |