Back to Repositories

Testing Sentinel DataSource Handler Implementation in Spring Cloud Alibaba

This test suite validates the functionality of the SentinelDataSourceHandler class in Spring Cloud Alibaba’s Sentinel module. It focuses on testing data source configuration parsing and bean definition handling for Sentinel’s Apollo data source integration.

Test Coverage Overview

The test suite provides comprehensive coverage of the SentinelDataSourceHandler’s core functionality, particularly the parseBeanDefinition method.

Key areas tested include:
  • Apollo data source properties configuration
  • Bean definition creation and validation
  • Property value assignment verification
  • Converter bean reference handling

Implementation Analysis

The testing approach utilizes JUnit and Mockito frameworks to create isolated unit tests. It implements a systematic verification of bean definition building process, ensuring proper configuration of Apollo data source properties and correct runtime bean references.

The implementation uses mock objects for DefaultListableBeanFactory, SentinelProperties, and Environment to isolate the tested components.

Technical Details

Testing tools and configuration:
  • JUnit 4 for test execution
  • Mockito for dependency mocking
  • AssertJ for fluent assertions
  • Spring Framework’s bean factory infrastructure
  • Custom test setup using @Before annotation

Best Practices Demonstrated

The test suite exemplifies several testing best practices including proper test isolation, clear test method naming, and comprehensive assertion coverage.

Notable practices include:
  • Thorough setup initialization
  • Explicit test case documentation
  • Granular property verification
  • Clean separation of concerns

alibaba/spring-cloud-alibaba

spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/custom/SentinelDataSourceHandlerTests.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.sentinel.custom;

import com.alibaba.cloud.sentinel.SentinelProperties;
import com.alibaba.cloud.sentinel.datasource.RuleType;
import com.alibaba.cloud.sentinel.datasource.config.AbstractDataSourceProperties;
import com.alibaba.cloud.sentinel.datasource.config.ApolloDataSourceProperties;
import org.junit.Before;
import org.junit.Test;

import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.env.Environment;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;

/**
 * Test cases for {@link SentinelDataSourceHandler}.
 *
 * @author <a href="mailto:[email protected]">hnyyghk</a>
 */
public class SentinelDataSourceHandlerTests {

	private SentinelDataSourceHandler sentinelDataSourceHandler;

	private DefaultListableBeanFactory beanFactory;

	private SentinelProperties sentinelProperties;

	private Environment env;

	@Before
	public void setUp() {
		beanFactory = mock(DefaultListableBeanFactory.class);
		sentinelProperties = mock(SentinelProperties.class);
		env = mock(Environment.class);
		sentinelDataSourceHandler = new SentinelDataSourceHandler(beanFactory, sentinelProperties, env);
	}

	/**
	 * Test cases for {@link SentinelDataSourceHandler#parseBeanDefinition(AbstractDataSourceProperties, String)}.
	 *
	 * @see com.alibaba.cloud.sentinel.datasource.config.ApolloDataSourceProperties
	 * @see com.alibaba.cloud.sentinel.datasource.factorybean.ApolloDataSourceFactoryBean
	 */
	@Test
	public void testParseBeanDefinition() {
		ApolloDataSourceProperties dataSourceProperties = new ApolloDataSourceProperties();
		dataSourceProperties.setNamespaceName("application");
		dataSourceProperties.setFlowRulesKey("test-flow-rules");
		dataSourceProperties.setDefaultFlowRuleValue("[]");
		dataSourceProperties.setDataType("json");
		dataSourceProperties.setRuleType(RuleType.FLOW);
		String dataSourceName = "ds1" + "-sentinel-" + "apollo" + "-datasource";

		//init BeanDefinitionBuilder for ApolloDataSourceFactoryBean
		BeanDefinitionBuilder builder = sentinelDataSourceHandler.parseBeanDefinition(dataSourceProperties, dataSourceName);
		MutablePropertyValues propertyValues = builder.getBeanDefinition().getPropertyValues();

		//ApolloDataSourceFactoryBean has four parameters, $jacocoData should not be included
		assertThat(propertyValues.size()).isEqualTo(4);
		assertThat(propertyValues).noneMatch(propertyValue -> "$jacocoData".equals(propertyValue.getName()));
		assertThat(propertyValues).anyMatch(propertyValue -> "flowRulesKey".equals(propertyValue.getName())
				&& dataSourceProperties.getFlowRulesKey().equals(propertyValue.getValue()));
		assertThat(propertyValues).anyMatch(propertyValue -> "defaultFlowRuleValue".equals(propertyValue.getName())
				&& dataSourceProperties.getDefaultFlowRuleValue().equals(propertyValue.getValue()));
		assertThat(propertyValues).anyMatch(propertyValue -> "namespaceName".equals(propertyValue.getName())
				&& dataSourceProperties.getNamespaceName().equals(propertyValue.getValue()));
		assertThat(propertyValues).anyMatch(propertyValue -> "converter".equals(propertyValue.getName())
				&& propertyValue.getValue() instanceof RuntimeBeanReference value
				&& value.getBeanName().equals("sentinel-" + dataSourceProperties.getDataType() + "-" + dataSourceProperties.getRuleType().getName() + "-converter"));
	}

}