1

尝试为 CircuitBreaker 代码示例编写单元测试时出现以下错误。

org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为 'com.foosball.team.Service.TeamServiceUnitTest' 的 bean 时出错:通过字段 'registry' 表示不满足的依赖关系;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有“io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry”类型的合格 bean 可用:预计至少有 1 个有资格作为自动装配候选者的 bean。依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true)}

团队服务:

@Service
public class TeamService {

    @Autowired
    private ITeamRepository teamRepository;

    @Autowired
    private PlayerClient playerClient;

    Logger logger = LoggerFactory.getLogger(TeamService.class);
    .
    .
    .

团队服务单元测试:

@SpringBootTest(classes = {
        TeamService.class
})
@RunWith(SpringRunner.class)
@DirtiesContext
public class TeamServiceUnitTest extends AbstractCircuitBreakerTest {

    @MockBean
    private ITeamRepository teamRepository;

    @MockBean
    private PlayerClient playerClient;

    @Autowired
    private TeamService service;

    private TeamEntity teamEntity;

    private Logger logger = LoggerFactory.getLogger(TeamServiceUnitTest.class);

    @Before
    public void setUp(){
        teamEntity = new TeamEntity();
        teamEntity.setId(1L);
        teamEntity.setPlayerOne("One");
        teamEntity.setPlayerTwo("Two");
        teamEntity.setPlayerThree("Three");
        teamEntity.setPlayerFour("Four");
    }

    @Test
    @DisplayName("when Player Client Fails 11 Times Then CircuitBreaker Should Be In OPEN State")
    public void whenPlayerClientFailsElevenTimesThenCircuitBreakerShouldBeInOPENState(){
        //Given
        when(teamRepository.findAll()).thenReturn(new ArrayList<>());
        when(playerClient.get(Mockito.anyString())).thenThrow(new RuntimeException());


        //When
        for(int i=0; i<11; i++){
            try {
                service.addTeam(teamEntity);
            } catch (Exception ignore) {
                logger.info(ignore.getClass().getName());
            }
        }

        //Then
        checkHealthStatus(BACKEND_B, CircuitBreaker.State.OPEN);
    }

}

参考等级:

public class AbstractCircuitBreakerTest {

    protected static final String BACKEND_A = "backendA";
    protected static final String BACKEND_B = "playerClientCircuitBreaker";

    @Autowired
    protected CircuitBreakerRegistry registry;

    @Before
    public void setup(){
        transitionToClosedState(BACKEND_A);
        transitionToClosedState(BACKEND_B);
    }

    protected void checkHealthStatus(String circuitBreakerName, CircuitBreaker.State state) {
        CircuitBreaker circuitBreaker = registry.circuitBreaker(circuitBreakerName);
        assertThat(circuitBreaker.getState()).isEqualTo(state);
    }

    protected void transitionToOpenState(String circuitBreakerName) {
        CircuitBreaker circuitBreaker = registry.circuitBreaker(circuitBreakerName);
        if(!circuitBreaker.getState().equals(CircuitBreaker.State.OPEN)){
            circuitBreaker.transitionToOpenState();
        }
    }

    protected void transitionToClosedState(String circuitBreakerName) {
        CircuitBreaker circuitBreaker = registry.circuitBreaker(circuitBreakerName);
        if(!circuitBreaker.getState().equals(CircuitBreaker.State.CLOSED)){
            circuitBreaker.transitionToClosedState();
        }
    }
}

参考项目:https ://github.com/resilience4j/resilience4j-spring-boot2-demo

提议的 Soln 讨论:https ://github.com/resilience4j/resilience4j-spring-boot2-demo/issues/33

提议的 Soln 项目:https ://github.com/shah-smit/resilience4j-spring-boot2-demo-maven

4

2 回答 2

1

看起来您尝试在测试中自动装配的 CircuitBreakerRegistry 是工厂类,而不是 bean。而不是 @Autowired protected CircuitBreakerRegistry registry;
尝试: protected CircuitBreakerRegistry registry = CircuitBreakerRegistry.ofDefaults()

于 2020-03-09T14:52:09.500 回答
0

这是关于不工作测试的答案。
这里有几件事:
1. UsingCircuitBreakerRegistry.ofDefaults()每次都会创建新的对象实例,因此CircuitBreakerRegistry您使用的对象AbstractCircuitBreakerTestHomeService不同的实例。您可能应该回到@Autowired注释,但首先您需要定义CircuitBreakerRegistry这样的 bean:

public class CircuitBreakerConfiguration {

    @Bean
    public CircuitBreakerRegistry circuitBreakerRegistry() {
        return CircuitBreakerRegistry.ofDefaults();
    }
}
  1. 您正在使用@RunWith(SpringRunner.class),但它只是 Junit 注释,它不会在您的测试中初始化 Spring Context。您正在测试中自动装配 bean,因此您需要 Spring Context。为此还添加@SpringBootTest注释。
  2. 您期望注册表状态在 11 次方法调用后BACKEND_A更改,但我看不到方法的任何用法。OPENservice.getGreeting()transitionToOpenState
于 2020-03-10T07:39:48.313 回答