Back to Repositories

Testing Hystrix Command Property Inheritance Configuration in Netflix/Hystrix

This test suite validates the default properties and inheritance behavior of Hystrix commands in Netflix’s Hystrix library. It focuses on verifying how command configurations are applied and overridden using annotations.

Test Coverage Overview

The test suite provides comprehensive coverage of Hystrix command configuration inheritance patterns.

  • Tests default group key inheritance and override scenarios
  • Validates thread pool key inheritance and customization
  • Verifies command property inheritance and override behavior
  • Tests thread pool property inheritance and configuration

Implementation Analysis

The testing approach uses JUnit to systematically verify Hystrix command configurations. It employs a base test class pattern with abstract service creation, allowing for flexible implementation across different contexts.

The tests utilize HystrixRequestLog to inspect command execution details and verify property applications through assertion-based validation.

Technical Details

  • Testing Framework: JUnit
  • Key Classes: HystrixInvokableInfo, HystrixRequestLog, HystrixThreadPoolProperties
  • Annotations: @DefaultProperties, @HystrixCommand, @HystrixProperty
  • Configuration Properties: Thread timeouts, queue sizes, group keys, thread pool keys

Best Practices Demonstrated

The test suite demonstrates excellent testing practices through clear separation of concerns and systematic validation.

  • Abstract base class pattern for reusable test infrastructure
  • Focused test methods with single responsibility
  • Consistent setup and teardown handling
  • Clear test naming conventions reflecting test purposes

netflix/hystrix

hystrix-contrib/hystrix-javanica/src/test/java/com/netflix/hystrix/contrib/javanica/test/common/configuration/command/BasicCommandDefaultPropertiesTest.java

            
package com.netflix.hystrix.contrib.javanica.test.common.configuration.command;

import com.netflix.hystrix.HystrixInvokableInfo;
import com.netflix.hystrix.HystrixRequestLog;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.test.common.BasicHystrixTest;
import org.junit.Before;
import org.junit.Test;

import static com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager.EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS;
import static org.junit.Assert.assertEquals;

/**
 * Created by dmgcodevil.
 */
public abstract class BasicCommandDefaultPropertiesTest extends BasicHystrixTest {

    private Service service;

    protected abstract Service createService();

    @Before
    public void setUp() throws Exception {
        service = createService();
    }

    @Test
    public void testCommandInheritsDefaultGroupKey() {
        service.commandInheritsDefaultProperties();
        HystrixInvokableInfo<?> command = HystrixRequestLog.getCurrentRequest()
                .getAllExecutedCommands().iterator().next();
        assertEquals("DefaultGroupKey", command.getCommandGroup().name());
    }

    @Test
    public void testCommandOverridesDefaultGroupKey() {
        service.commandOverridesGroupKey();
        HystrixInvokableInfo<?> command = HystrixRequestLog.getCurrentRequest()
                .getAllExecutedCommands().iterator().next();
        assertEquals("SpecificGroupKey", command.getCommandGroup().name());
    }

    @Test
    public void testCommandInheritsDefaultThreadPoolKey() {
        service.commandInheritsDefaultProperties();
        HystrixInvokableInfo<?> command = HystrixRequestLog.getCurrentRequest()
                .getAllExecutedCommands().iterator().next();
        assertEquals("DefaultThreadPoolKey", command.getThreadPoolKey().name());
    }

    @Test
    public void testCommandOverridesDefaultThreadPoolKey() {
        service.commandOverridesThreadPoolKey();
        HystrixInvokableInfo<?> command = HystrixRequestLog.getCurrentRequest()
                .getAllExecutedCommands().iterator().next();
        assertEquals("SpecificThreadPoolKey", command.getThreadPoolKey().name());
    }

    @Test
    public void testCommandInheritsDefaultCommandProperties() {
        service.commandInheritsDefaultProperties();
        HystrixInvokableInfo<?> command = HystrixRequestLog.getCurrentRequest()
                .getAllExecutedCommands().iterator().next();
        assertEquals(456, command.getProperties().executionTimeoutInMilliseconds().get().intValue());
    }

    @Test
    public void testCommandOverridesDefaultCommandProperties() {
        service.commandOverridesDefaultCommandProperties();
        HystrixInvokableInfo<?> command = HystrixRequestLog.getCurrentRequest()
                .getAllExecutedCommands().iterator().next();
        assertEquals(654, command.getProperties().executionTimeoutInMilliseconds().get().intValue());
    }

    @Test
    public void testCommandInheritsThreadPollProperties() {
        service.commandInheritsDefaultProperties();
        HystrixInvokableInfo<?> command = HystrixRequestLog.getCurrentRequest()
                .getAllExecutedCommands().iterator().next();

        HystrixThreadPoolProperties properties = getThreadPoolProperties(command);

        assertEquals(123, properties.maxQueueSize().get().intValue());
    }

    @Test
    public void testCommandOverridesDefaultThreadPollProperties() {
        service.commandOverridesDefaultThreadPoolProperties();
        HystrixInvokableInfo<?> command = HystrixRequestLog.getCurrentRequest()
                .getAllExecutedCommands().iterator().next();

        HystrixThreadPoolProperties properties = getThreadPoolProperties(command);

        assertEquals(321, properties.maxQueueSize().get().intValue());
    }

    @DefaultProperties(groupKey = "DefaultGroupKey", threadPoolKey = "DefaultThreadPoolKey",
            commandProperties = {
                    @HystrixProperty(name = EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS, value = "456")
            },
            threadPoolProperties = {
                    @HystrixProperty(name = "maxQueueSize", value = "123")
            }
    )
    public static class Service {

        @HystrixCommand
        public Object commandInheritsDefaultProperties() {
            return null;
        }

        @HystrixCommand(groupKey = "SpecificGroupKey")
        public Object commandOverridesGroupKey() {
            return null;
        }

        @HystrixCommand(threadPoolKey = "SpecificThreadPoolKey")
        public Object commandOverridesThreadPoolKey() {
            return null;
        }

        @HystrixCommand(commandProperties = {
                @HystrixProperty(name = EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS, value = "654")
        })
        public Object commandOverridesDefaultCommandProperties() {
            return null;
        }

        @HystrixCommand(threadPoolProperties = {
                @HystrixProperty(name = "maxQueueSize", value = "321")
        })
        public Object commandOverridesDefaultThreadPoolProperties() {
            return null;
        }
    }
}