我正在使用
javanica并注释我的hystrix命令方法,如下所示:
@HystrixCommand(groupKey="MY_GROUP",commandKey="MY_COMMAND" fallbackMethod="fallbackMethod") public Object getSomething(Object request) { ....
我试图对我的回退方法进行单元测试,而不必直接调用它们,即我想调用@HystrixCommand带注释的方法,让它在抛出500错误后自然流入回退.这一切都在单元测试之外工作.
在我的单元测试中,我使用spring MockRestServiceServer返回500个错误,这部分工作正常,但Hystrix没有在我的单元测试中正确初始化.在我的测试方法开始时,我有:
HystrixRequestContext context = HystrixRequestContext.initializeContext(); myService.myHystrixCommandAnnotatedMethod();
在此之后,我试图通过键获取任何hystrix命令并检查是否有任何已执行的命令,但列表始终为空,我使用此方法:
public static HystrixInvokableInfo<?> getHystrixCommandByKey(String key) { HystrixInvokableInfo<?> hystrixCommand = null; System.out.println("Current request is " + HystrixRequestLog.getCurrentRequest()); Collection<HystrixInvokableInfo<?>> executedCommands = HystrixRequestLog.getCurrentRequest() .getAllExecutedCommands(); for (HystrixInvokableInfo<?> command : executedCommands) { System.out.println("executed command is " + command.getCommandGroup().name()); if (command.getCommandKey().name().equals(key)) { hystrixCommand = command; break; } } return hystrixCommand; }
我意识到我在单元测试初始化中遗漏了一些东西,任何人都可以指出我正确的方向如何正确地进行单元测试吗?
解决方法
虽然你不一定要UNIT测试hystrix命令.进行一种弹簧混合测试仍然很有用,我认为在添加注释时接受功能的空白是不正确的.我创建的测试确保断路器在例外情况下打开.
@RunWith(SpringRunner.class) @SpringBootTest public class HystrixProxyServiceTests { @MockBean private MyRepo myRepo; @Autowired private MyService myService; private static final String ID = “1”; @Before public void setup() { resetHystrix(); openCircuitBreakerAfterOneFailingRequest(); } @Test public void circuitBreakerClosedOnSuccess() throws IOException,InterruptedException { when(myRepo.findOneById(USER_ID1)) .thenReturn(Optional.of(Document.builder().build())); myService.findOneById(USER_ID1); HystrixCircuitBreaker circuitBreaker = getCircuitBreaker(); Assert.assertTrue(circuitBreaker.allowRequest()); verify(myRepo,times(1)).findOneById( any(String.class)); } @Test public void circuitBreakerOpenOnException() throws IOException,InterruptedException { when(myRepo.findOneById(ID)) .thenThrow(new RuntimeException()); try { myService.findOneById(ID); } catch (RuntimeException exception) { waitUntilCircuitBreakerOpens(); HystrixCircuitBreaker circuitBreaker = getCircuitBreaker(); Assert.assertFalse(circuitBreaker.allowRequest()); } verify(myRepo,times(1)).findOneById( any(String.class)); } private void waitUntilCircuitBreakerOpens() throws InterruptedException { Thread.sleep(1000); } private void resetHystrix() { Hystrix.reset(); } private void warmUpCircuitBreaker() { myService.findOneById(USER_ID1); } public static HystrixCircuitBreaker getCircuitBreaker() { return HystrixCircuitBreaker.Factory.getInstance(getCommandKey()); } private static HystrixCommandKey getCommandKey() { return HystrixCommandKey.Factory.asKey("findOneById"); } private void openCircuitBreakerAfterOneFailingRequest() { ConfigurationManager.getConfigInstance(). setProperty("hystrix.command.findOneById.circuitBreaker.requestVolumeThreshold",1); } }
让我吵架一段时间的另一件小事是我输入了没有特定命令键的默认注释,但是当创建命令键时,它们是根据我在上面指定的方法名称创建的.对于一个完整的例子,我还添加了注释,以表明我没有指定commandKey.
@HystrixCommand public Optional<Document> findOneById(final String id) { return this.myRepo.findOneById(id); }
希望这有助于某人.