Back to Repositories

Testing Sentinel Circuit Breaker Implementation in Spring Cloud Alibaba

This test suite validates the Sentinel Circuit Breaker implementation in Spring Cloud Alibaba, focusing on circuit breaker creation, execution, and fallback behavior. The tests ensure proper integration between Sentinel’s degradation rules and Spring Cloud’s circuit breaker interface.

Test Coverage Overview

The test suite provides comprehensive coverage of the Sentinel Circuit Breaker functionality:

  • Direct circuit breaker creation and execution
  • Circuit breaker creation with and without degradation rules
  • Null rule handling scenarios
  • Factory-based circuit breaker creation
  • Fallback mechanism verification

Implementation Analysis

The testing approach employs JUnit 5 framework with a focus on behavior verification. Each test case isolates specific circuit breaker functionality, using AssertJ for assertions and proper test cleanup through @AfterEach annotations. The implementation demonstrates integration between Spring Cloud’s CircuitBreaker interface and Sentinel’s DegradeRuleManager.

Technical Details

Testing tools and configuration:

  • JUnit Jupiter for test execution
  • AssertJ for fluent assertions
  • Sentinel DegradeRuleManager for rule management
  • Spring Cloud CircuitBreaker interface implementation
  • Test cleanup mechanism for rule isolation

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Proper test isolation through tearDown methods
  • Clear test method naming conventions
  • Comprehensive edge case coverage
  • Effective use of assertion libraries
  • Clean separation of test scenarios

alibaba/spring-cloud-alibaba

spring-cloud-alibaba-starters/spring-cloud-circuitbreaker-sentinel/src/test/java/com/alibaba/cloud/circuitbreaker/sentinel/SentinelCircuitBreakerTest.java

            
/*
 * Copyright 2013-2023 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.alibaba.cloud.circuitbreaker.sentinel;

import java.util.ArrayList;
import java.util.Collections;

import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import org.springframework.cloud.client.circuitbreaker.CircuitBreaker;

import static org.assertj.core.api.Assertions.assertThat;

/**
 * @author Eric Zhao
 */
public class SentinelCircuitBreakerTest {

	@AfterEach
	public void tearDown() {
		// Clear the rules.
		DegradeRuleManager.loadRules(new ArrayList<>());
	}

	@Test
	public void testCreateDirectlyThenRun() {
		// Create a circuit breaker without any circuit breaking rules.
		CircuitBreaker cb = new SentinelCircuitBreaker(
				"testSentinelCreateDirectlyThenRunA");
		assertThat(cb.run(() -> "Sentinel")).isEqualTo("Sentinel");
		assertThat(DegradeRuleManager.hasConfig("testSentinelCreateDirectlyThenRunA"))
				.isFalse();

		CircuitBreaker cb2 = new SentinelCircuitBreaker(
				"testSentinelCreateDirectlyThenRunB",
				Collections.singletonList(
						new DegradeRule("testSentinelCreateDirectlyThenRunB")
								.setCount(100).setTimeWindow(10)));
		assertThat(cb2.run(() -> "Sentinel")).isEqualTo("Sentinel");
		assertThat(DegradeRuleManager.hasConfig("testSentinelCreateDirectlyThenRunB"))
				.isTrue();
	}

	@Test
	public void testCreateWithNullRule() {
		String id = "testCreateCbWithNullRule";
		CircuitBreaker cb = new SentinelCircuitBreaker(id,
				Collections.singletonList(null));
		assertThat(cb.run(() -> "Sentinel")).isEqualTo("Sentinel");
		assertThat(DegradeRuleManager.hasConfig(id)).isFalse();
	}

	@Test
	public void testCreateFromFactoryThenRun() {
		CircuitBreaker cb = new SentinelCircuitBreakerFactory().create("testSentinelRun");
		assertThat(cb.run(() -> "foobar")).isEqualTo("foobar");
	}

	@Test
	public void testRunWithFallback() {
		CircuitBreaker cb = new SentinelCircuitBreakerFactory()
				.create("testSentinelRunWithFallback");
		assertThat(cb.<String>run(() -> {
			throw new RuntimeException("boom");
		}, t -> "fallback")).isEqualTo("fallback");
	}

}