spec/reporter.rb in health-reporter-0.2.1 vs spec/reporter.rb in health-reporter-0.3.0
- old
+ new
@@ -16,11 +16,11 @@
subject.clear_dependencies
Timecop.return
reset_lambda_runner_spy
end
- context 'when configuring' do
+ describe '#self_test' do
it 'remembers the self-test lambda passed to it' do
test_lambda = lambda{ 'ab' == 'cd' }
subject.self_test = test_lambda
expect(subject.self_test).to be test_lambda
end
@@ -30,33 +30,39 @@
subject.self_test = test_lambda
expect(subject.self_test).to be test_lambda
expect(subject.healthy?).to be false
expect(spy_lambda_was_run?).to eq true
end
+ end
+ describe '#healthy_cache_ttl' do
it 'remembers the cache ttl when healthy' do
subject.healthy_cache_ttl = 10
expect(subject.healthy_cache_ttl).to eq 10
end
+ end
+ describe '#unhealthy_cache_ttl' do
it 'remembers the cache ttl when not healthy' do
subject.unhealthy_cache_ttl = 5
expect(subject.unhealthy_cache_ttl).to eq 5
end
+ end
- it 'remembers when you add a dependencies' do
+ describe '#register_dependency' do
+ it 'remembers when you add a dependency' do
subject.register_dependency(url: 'https://hardware-store/status', code: 123, timeout: 1)
expect(subject.dependencies).to eq({
'https://hardware-store/status' => { :code => 123, :timeout => 1 }
})
end
- it 'validates the urls of the dependencies during registration' do
+ it 'validates the urls of the dependency during registration' do
expect{subject.register_dependency(url: 'no-valid-url')}.to raise_error RuntimeError, "Configured URL no-valid-url is invalid"
end
- it 'adds dependencies without removing the dependencies already registered' do
+ it 'adds dependency without removing the dependencies already registered' do
subject.register_dependency(url: 'https://hardware-store/status', code: 123, timeout: 1)
subject.register_dependency(url: 'https://grocery-store/status', code: 123, timeout: 1)
expect(subject.dependencies).to eq({
'https://hardware-store/status' => { :code => 123, :timeout => 1 },
'https://grocery-store/status' => { :code => 123, :timeout => 1 }
@@ -72,217 +78,391 @@
expect(subject.dependencies).to eq({
'https://hardware-store/status' => { :code => 123, :timeout => 1 },
'https://grocery-store/status' => { :code => 123, :timeout => 1 }
})
end
-
- it 'clears the cache when requested' do
- subject.healthy?
- expect(subject.class_variable_get('@@healthy')).to be true
- expect(subject.class_variable_get('@@last_check_time')).to_not be nil
- subject.clear_cache
- expect(subject.class_variable_get('@@healthy')).to be nil
- expect(subject.class_variable_get('@@last_check_time')).to be nil
- end
end
- context 'when exercising self-test lambda' do
- it 'allows true to be returned by self-test lambda' do
- test_lambda = lambda{ true }
- subject.self_test = test_lambda
- expect(subject.healthy?).to be true
- end
- it 'allows false to be returned by self-test lambda' do
- test_lambda = lambda{ false }
- subject.self_test = test_lambda
- expect(subject.healthy?).to be false
- end
-
- it 'raises an exception when non-boolean values are returned by self-test lambda' do
- test_lambda = lambda{ "I don't feel well..." }
- subject.self_test = test_lambda
- expect{subject.healthy?}.to raise_error RuntimeError, "Invalid non-boolean response from registered self-check lambda: I don't feel well..."
- end
+ def self.register_dependencies(provided_dependencies = [])
+ provided_dependencies.map{ |dependency|
+ @@dependencies[url] = dependency.delete(:url)
+ }
end
- context 'when initialized without any parameters' do
- it 'sets the default self-test lambda to { true }' do
- expect(subject.healthy?).to eq true
- end
- it 'sets the default healthy state cache ttl to 60 seconds' do
- expect(subject.healthy_cache_ttl).to eq 60
+ describe '#register_dependencies' do
+ let(:provided_test_dependencies_with_string_keys) {
+ [
+ {
+ "url" => "https://cake-place/health",
+ "code" => 200,
+ "timeout" => 3
+ },
+ {
+ "url" => "https://coffee-place/status",
+ "code" => 200,
+ "timeout" => 3
+ },
+ {
+ "url" => "http://postoffice/status",
+ "code" => 200,
+ "timeout" => 3
+ },
+ {
+ "url" => "http://postoffice/status",
+ "code" => 200,
+ "timeout" => 3,
+ "authorization_token" => "api_token"
+ },
+ {
+ "url" => "http://duplicated/status",
+ "code" => 200,
+ "timeout" => 3,
+ "authorization_token" => "api_token"
+ },
+ {
+ "url" => "http://duplicated/status",
+ "code" => 200,
+ "timeout" => 3,
+ "authorization_token" => "api_token"
+ },
+ {
+ "url" => "https://pizza-place/health",
+ "code" => 204,
+ "timeout" => 2,
+ "username" => "checker",
+ "password" => "checking"
+ }
+ ]
+ }
+ let(:provided_test_dependencies_with_symbol_keys) {
+ [
+ {
+ url: "https://cake-place/health",
+ code: 200,
+ timeout: 3
+ },
+ {
+ url: "https://coffee-place/status",
+ code: 200,
+ timeout: 3
+ },
+ {
+ url: "http://postoffice/status",
+ code: 200,
+ timeout: 3
+ },
+ {
+ url: "http://postoffice/status",
+ code: 200,
+ timeout: 3,
+ authorization_token: "api_token"
+ },
+ {
+ url: "http://duplicated/status",
+ code: 200,
+ timeout: 3,
+ authorization_token: "api_token"
+ },
+ {
+ url: "http://duplicated/status",
+ code: 200,
+ timeout: 3,
+ authorization_token: "api_token"
+ },
+ {
+ url: "https://pizza-place/health",
+ code: 204,
+ timeout: 2,
+ username: "checker",
+ password: "checking"
+ }
+ ]
+ }
+ let(:expected_dependencies) {
+ {
+ "https://cake-place/health" => {
+ code: 200,
+ timeout: 3
+ },
+ "https://coffee-place/status" => {
+ code: 200,
+ timeout: 3
+ },
+ "http://postoffice/status" => {
+ code: 200,
+ timeout: 3,
+ authorization_token: "api_token"
+ },
+ "http://duplicated/status" => {
+ code: 200,
+ timeout: 3,
+ authorization_token: "api_token"
+ },
+ "https://pizza-place/health" => {
+ code: 204,
+ timeout: 2,
+ username: "checker",
+ password: "checking"
+ }
+ }
+ }
+ it 'remembers when you add the dependencies with string keys' do
+ subject.register_dependencies(provided_test_dependencies_with_string_keys)
+ expect(subject.dependencies).to eq(expected_dependencies)
end
-
- it 'sets the default unhealthy state cache ttl to 30 seconds' do
- expect(subject.unhealthy_cache_ttl).to eq 30
+ it 'remembers when you add the dependencies with symbol keys' do
+ subject.register_dependencies(provided_test_dependencies_with_symbol_keys)
+ expect(subject.dependencies).to eq(expected_dependencies)
end
+
+
end
- context 'when calling health check for first time (no cached health state)' do
- it 'calls the configured self-test lambda and returns health' do
- subject.self_test = spy_lambda_returning_false
- expect(subject.healthy?).to be false
- expect(spy_lambda_was_run?).to eq true
+ describe '#clear_cache' do
+ it 'clears the cache when requested' do
+ subject.healthy?
+ expect(subject.class_variable_get('@@healthy')).to be true
+ expect(subject.class_variable_get('@@last_check_time')).to_not be nil
+ subject.clear_cache
+ expect(subject.class_variable_get('@@healthy')).to be nil
+ expect(subject.class_variable_get('@@last_check_time')).to be nil
end
end
- context 'when current state is healty' do
- before(:each) do
- subject.self_test = spy_lambda_returning_true
- subject.healthy? #force the self-test
- reset_lambda_runner_spy #reset the spy so that we can see if it was run or not
- end
-
- context 'when neither healty-cache-ttl nor unhealty-cache-ttl has expired' do
- before(:each) do
- subject.unhealthy_cache_ttl = 10
- subject.healthy_cache_ttl = 10
- Timecop.freeze(Time.now + 5)
- end
-
- it 'does not call the registered self-test lambda' do
- subject.healthy? #request here and test if it was run in expect below
- expect(spy_lambda_was_run?).to eq false
- end
- it 'returns the current healthy state' do
+ describe '#healthy?' do
+ context 'when exercising self-test lambda' do
+ it 'allows true to be returned by self-test lambda' do
+ test_lambda = lambda{ true }
+ subject.self_test = test_lambda
expect(subject.healthy?).to be true
end
- end
-
- context 'when healty-cache-ttl has expired' do
- before do
- subject.unhealthy_cache_ttl = 10
- subject.healthy_cache_ttl = 3
- Timecop.freeze(Time.now + 5)
+
+ it 'allows false to be returned by self-test lambda' do
+ test_lambda = lambda{ false }
+ subject.self_test = test_lambda
+ expect(subject.healthy?).to be false
end
-
- it 'calls the registered self-test lambda' do
- subject.healthy? #request here and test if it was run in expect below
- expect(spy_lambda_was_run?).to eq true
+
+ it 'raises an exception when non-boolean values are returned by self-test lambda' do
+ test_lambda = lambda{ "I don't feel well..." }
+ subject.self_test = test_lambda
+ expect{subject.healthy?}.to raise_error RuntimeError, "Invalid non-boolean response from registered self-check lambda: I don't feel well..."
end
- it 'returns the current healthy state' do
- expect(subject.healthy?).to be true
- end
end
-
- context 'when unhealty-cache-ttl has expired' do
- before(:each) do
- subject.unhealthy_cache_ttl = 3
- subject.healthy_cache_ttl = 10
- Timecop.freeze(Time.now + 5)
+
+ context 'when initialized without any parameters' do
+ it 'sets the default self-test lambda to { true }' do
+ expect(subject.healthy?).to eq true
end
-
- it 'does not call the registered self-test lambda' do
- subject.healthy? #request here and test if it was run in expect below
- expect(spy_lambda_was_run?).to eq false
+
+ it 'sets the default healthy state cache ttl to 60 seconds' do
+ expect(subject.healthy_cache_ttl).to eq 60
end
- it 'returns the current healthy state' do
- expect(subject.healthy?).to be true
+
+ it 'sets the default unhealthy state cache ttl to 30 seconds' do
+ expect(subject.unhealthy_cache_ttl).to eq 30
end
end
- end
-
- context 'when current state is unhealty' do
- before(:each) do
- subject.self_test = spy_lambda_returning_false
- subject.healthy? #force the self-test
- reset_lambda_runner_spy #reset the spy so that we can see if it was run or not
- end
-
- context 'when neither healty-cache-ttl nor unhealty-cache-ttl has expired' do
- before(:each) do
- subject.unhealthy_cache_ttl = 10
- subject.healthy_cache_ttl = 10
- Timecop.freeze(Time.now + 5)
- end
-
- it 'does not call the registered self-test lambda' do
- subject.healthy? #request here and test if it was run in expect below
- expect(spy_lambda_was_run?).to eq false
- end
- it 'returns the current unhealthy state' do
+
+ context 'when calling health check for first time (no cached health state)' do
+ it 'calls the configured self-test lambda and returns health' do
+ subject.self_test = spy_lambda_returning_false
expect(subject.healthy?).to be false
+ expect(spy_lambda_was_run?).to eq true
end
end
-
- context 'when healty-cache-ttl has expired' do
+
+ context 'when current state is healty' do
before(:each) do
- subject.unhealthy_cache_ttl = 10
- subject.healthy_cache_ttl = 3
- Timecop.freeze(Time.now + 5)
+ subject.self_test = spy_lambda_returning_true
+ subject.healthy? #force the self-test
+ reset_lambda_runner_spy #reset the spy so that we can see if it was run or not
end
-
- it 'does not call the registered self-test lambda' do
- subject.healthy? #request here and test if it was run in expect below
- expect(spy_lambda_was_run?).to eq false
+
+ context 'when neither healty-cache-ttl nor unhealty-cache-ttl has expired' do
+ before(:each) do
+ subject.unhealthy_cache_ttl = 10
+ subject.healthy_cache_ttl = 10
+ Timecop.freeze(Time.now + 5)
+ end
+
+ it 'does not call the registered self-test lambda' do
+ subject.healthy? #request here and test if it was run in expect below
+ expect(spy_lambda_was_run?).to eq false
+ end
+ it 'returns the current healthy state' do
+ expect(subject.healthy?).to be true
+ end
end
- it 'returns the current unhealthy state' do
- expect(subject.healthy?).to be false
+
+ context 'when healty-cache-ttl has expired' do
+ before do
+ subject.unhealthy_cache_ttl = 10
+ subject.healthy_cache_ttl = 3
+ Timecop.freeze(Time.now + 5)
+ end
+
+ it 'calls the registered self-test lambda' do
+ subject.healthy? #request here and test if it was run in expect below
+ expect(spy_lambda_was_run?).to eq true
+ end
+ it 'returns the current healthy state' do
+ expect(subject.healthy?).to be true
+ end
end
+
+ context 'when unhealty-cache-ttl has expired' do
+ before(:each) do
+ subject.unhealthy_cache_ttl = 3
+ subject.healthy_cache_ttl = 10
+ Timecop.freeze(Time.now + 5)
+ end
+
+ it 'does not call the registered self-test lambda' do
+ subject.healthy? #request here and test if it was run in expect below
+ expect(spy_lambda_was_run?).to eq false
+ end
+ it 'returns the current healthy state' do
+ expect(subject.healthy?).to be true
+ end
+ end
end
-
- context 'when unhealty-cache-ttl has expired' do
+
+ context 'when current state is unhealty' do
before(:each) do
- subject.unhealthy_cache_ttl = 3
- subject.healthy_cache_ttl = 10
- Timecop.freeze(Time.now + 5)
+ subject.self_test = spy_lambda_returning_false
+ subject.healthy? #force the self-test
+ reset_lambda_runner_spy #reset the spy so that we can see if it was run or not
end
-
- it 'calls the registered self-test lambda' do
- subject.healthy? #request here and test if it was run in expect below
- expect(spy_lambda_was_run?).to eq true
+
+ context 'when neither healty-cache-ttl nor unhealty-cache-ttl has expired' do
+ before(:each) do
+ subject.unhealthy_cache_ttl = 10
+ subject.healthy_cache_ttl = 10
+ Timecop.freeze(Time.now + 5)
+ end
+
+ it 'does not call the registered self-test lambda' do
+ subject.healthy? #request here and test if it was run in expect below
+ expect(spy_lambda_was_run?).to eq false
+ end
+ it 'returns the current unhealthy state' do
+ expect(subject.healthy?).to be false
+ end
end
- it 'returns the current unhealthy state' do
- expect(subject.healthy?).to be false
+
+ context 'when healty-cache-ttl has expired' do
+ before(:each) do
+ subject.unhealthy_cache_ttl = 10
+ subject.healthy_cache_ttl = 3
+ Timecop.freeze(Time.now + 5)
+ end
+
+ it 'does not call the registered self-test lambda' do
+ subject.healthy? #request here and test if it was run in expect below
+ expect(spy_lambda_was_run?).to eq false
+ end
+ it 'returns the current unhealthy state' do
+ expect(subject.healthy?).to be false
+ end
end
- end
- end
-
- context 'when checking dependencies' do
- context 'when there are no dependencies registered' do
- it 'only performs the self-test' do
- subject.self_test = spy_lambda_returning_false
- expect(subject.healthy?).to be false
- expect(spy_lambda_was_run?).to eq true
+
+ context 'when unhealty-cache-ttl has expired' do
+ before(:each) do
+ subject.unhealthy_cache_ttl = 3
+ subject.healthy_cache_ttl = 10
+ Timecop.freeze(Time.now + 5)
+ end
+
+ it 'calls the registered self-test lambda' do
+ subject.healthy? #request here and test if it was run in expect below
+ expect(spy_lambda_was_run?).to eq true
+ end
+ it 'returns the current unhealthy state' do
+ expect(subject.healthy?).to be false
+ end
end
end
-
- context 'when there are multiple dependencies registered' do
- before(:each) do
- subject.register_dependency(url: 'https://hardware-store/status')
- subject.register_dependency(url: 'https://grocery-store/status')
- subject.self_test = spy_lambda_returning_true
+
+ context 'when checking dependencies' do
+ context 'when there are no dependencies registered' do
+ it 'only performs the self-test' do
+ subject.self_test = spy_lambda_returning_false
+ expect(subject.healthy?).to be false
+ expect(spy_lambda_was_run?).to eq true
+ end
end
-
- it 'performs the self-test and checks all dependencies' do
- stub_request(:get, "https://hardware-store/status").to_return(:status => 200, :body => "", :headers => {})
- stub_request(:get, "https://grocery-store/status").to_return(:status => 200, :body => "", :headers => {})
- expect(subject.healthy?).to be true
- expect(spy_lambda_was_run?).to eq true
+
+ context 'when there are multiple dependencies registered' do
+ before(:each) do
+ subject.register_dependency(url: 'https://hardware-store/status')
+ subject.register_dependency(url: 'https://grocery-store/status')
+ subject.self_test = spy_lambda_returning_true
+ end
+
+ it 'performs the self-test and checks all dependencies' do
+ stub_request(:get, "https://hardware-store/status").to_return(:status => 200, :body => "", :headers => {})
+ stub_request(:get, "https://grocery-store/status").to_return(:status => 200, :body => "", :headers => {})
+ expect(subject.healthy?).to be true
+ expect(spy_lambda_was_run?).to eq true
+ end
+
+ it 'indicates healthy if all of the dependencies are healthy' do
+ stub_request(:get, "https://hardware-store/status").to_return(:status => 200, :body => "", :headers => {})
+ stub_request(:get, "https://grocery-store/status").to_return(:status => 200, :body => "", :headers => {})
+ expect(subject.healthy?).to be true
+ expect(spy_lambda_was_run?).to eq true
+ end
+
+ it 'raises a detailed exception indicating why a dependency was determined to be unhealthy state was uncached' do
+ stub_request(:get, "https://hardware-store/status").to_return(:status => 500, :body => "", :headers => {})
+ stub_request(:get, "https://grocery-store/status").to_return(:status => 200, :body => "", :headers => {})
+ expect{subject.healthy?}.to raise_error RuntimeError, "Dependency <https://hardware-store/status> failed check due to RuntimeError: Response expected to be 200 but is 500"
+ end
+
+ it 'indicates cached unhealthy state if it is unhealthy because a dependency was unhealthy' do
+ stub_request(:get, "https://hardware-store/status").to_return(:status => 500, :body => "", :headers => {})
+ stub_request(:get, "https://grocery-store/status").to_return(:status => 200, :body => "", :headers => {})
+ expect{subject.healthy?}.to raise_error RuntimeError, "Dependency <https://hardware-store/status> failed check due to RuntimeError: Response expected to be 200 but is 500"
+ reset_lambda_runner_spy
+ expect(subject.healthy?).to be false
+ expect(spy_lambda_was_run?).to eq false
+ end
end
- it 'indicates healthy if all of the dependencies are healthy' do
- stub_request(:get, "https://hardware-store/status").to_return(:status => 200, :body => "", :headers => {})
- stub_request(:get, "https://grocery-store/status").to_return(:status => 200, :body => "", :headers => {})
- expect(subject.healthy?).to be true
- expect(spy_lambda_was_run?).to eq true
- end
+ context 'when a dependency requires basic auth' do
+ let(:test_dependencies_with_basic_auth) {
+ [
+ {
+ url: "https://pizza-place/health",
+ code: 204,
+ timeout: 2,
+ username: "check_user",
+ password: "check_password"
+ }
+ ]
+ }
- it 'raises a detailed exception indicating why a dependency was determined to be unhealthy state was uncached' do
- stub_request(:get, "https://hardware-store/status").to_return(:status => 500, :body => "", :headers => {})
- stub_request(:get, "https://grocery-store/status").to_return(:status => 200, :body => "", :headers => {})
- expect{subject.healthy?}.to raise_error RuntimeError, "Dependency <https://hardware-store/status> failed check due to RuntimeError: Response expected to be 200 but is 500"
- end
+ before(:each) do
+ subject.register_dependencies(test_dependencies_with_basic_auth)
+ end
- it 'indicates cached unhealthy state if it is unhealthy because a dependency was unhealthy' do
- stub_request(:get, "https://hardware-store/status").to_return(:status => 500, :body => "", :headers => {})
- stub_request(:get, "https://grocery-store/status").to_return(:status => 200, :body => "", :headers => {})
- expect{subject.healthy?}.to raise_error RuntimeError, "Dependency <https://hardware-store/status> failed check due to RuntimeError: Response expected to be 200 but is 500"
- reset_lambda_runner_spy
- expect(subject.healthy?).to be false
- expect(spy_lambda_was_run?).to eq false
+ it 'reaches out to the dependency using a basic auth and dependency have good health' do
+ stub_request(:get, "https://pizza-place/health").
+ with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Basic Y2hlY2tfdXNlcjpjaGVja19wYXNzd29yZA==', 'User-Agent'=>'Faraday v0.15.2'}).
+ to_return(:status => 204, :body => "", :headers => {})
+ expect(subject.healthy?).to be true
+ end
+
+ it 'reaches out to the dependency using a basic auth and dependency does not have good health' do
+ stub_request(:get, "https://pizza-place/health").
+ with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Basic Y2hlY2tfdXNlcjpjaGVja19wYXNzd29yZA==', 'User-Agent'=>'Faraday v0.15.2'}).
+ to_return(:status => 500, :body => "", :headers => {})
+ expect{subject.healthy?}.to raise_error RuntimeError, "Dependency <https://pizza-place/health> failed check due to RuntimeError: Response expected to be 204 but is 500"
+ expect(subject.healthy?).to be false
+ end
end
end
end
end