@@ -257,5 +257,58 @@ public void FailOverTests_BackoffStateIsUpdatedOnSuccessfulRequest()
257257 // The client enumerator should return 2 clients for the third time.
258258 Assert . Equal ( 2 , configClientManager . GetAvailableClients ( DateTimeOffset . UtcNow ) . Count ( ) ) ;
259259 }
260+
261+ [ Fact ]
262+ public void FailOverTests_FailOverOnKeyVaultReferenceException ( )
263+ {
264+ // Arrange
265+ IConfigurationRefresher refresher = null ;
266+ var mockResponse = new Mock < Response > ( ) ;
267+
268+ var mockClient1 = new Mock < ConfigurationClient > ( ) ;
269+ mockClient1 . Setup ( c => c . GetConfigurationSettingsAsync ( It . IsAny < SettingSelector > ( ) , It . IsAny < CancellationToken > ( ) ) )
270+ . Throws ( new KeyVaultReferenceException ( "Key vault reference failed." , new RequestFailedException ( 503 , "Request failed." ) ) ) ;
271+ mockClient1 . Setup ( c => c . GetConfigurationSettingAsync ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < CancellationToken > ( ) ) )
272+ . Throws ( new KeyVaultReferenceException ( "Key vault reference failed." , new RequestFailedException ( 503 , "Request failed." ) ) ) ;
273+ mockClient1 . Setup ( c => c . GetConfigurationSettingAsync ( It . IsAny < ConfigurationSetting > ( ) , It . IsAny < bool > ( ) , It . IsAny < CancellationToken > ( ) ) )
274+ . Throws ( new KeyVaultReferenceException ( "Key vault reference failed." , new RequestFailedException ( 503 , "Request failed." ) ) ) ;
275+ mockClient1 . Setup ( c => c . Equals ( mockClient1 ) ) . Returns ( true ) ;
276+
277+ var mockClient2 = new Mock < ConfigurationClient > ( ) ;
278+ mockClient2 . Setup ( c => c . GetConfigurationSettingsAsync ( It . IsAny < SettingSelector > ( ) , It . IsAny < CancellationToken > ( ) ) )
279+ . Returns ( new MockAsyncPageable ( Enumerable . Empty < ConfigurationSetting > ( ) . ToList ( ) ) ) ;
280+ mockClient2 . Setup ( c => c . GetConfigurationSettingAsync ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < CancellationToken > ( ) ) )
281+ . Returns ( Task . FromResult ( Response . FromValue < ConfigurationSetting > ( kv , mockResponse . Object ) ) ) ;
282+ mockClient2 . Setup ( c => c . GetConfigurationSettingAsync ( It . IsAny < ConfigurationSetting > ( ) , It . IsAny < bool > ( ) , It . IsAny < CancellationToken > ( ) ) )
283+ . Returns ( Task . FromResult ( Response . FromValue < ConfigurationSetting > ( kv , mockResponse . Object ) ) ) ;
284+ mockClient2 . Setup ( c => c . Equals ( mockClient2 ) ) . Returns ( true ) ;
285+
286+ ConfigurationClientWrapper cw1 = new ConfigurationClientWrapper ( TestHelpers . PrimaryConfigStoreEndpoint , mockClient1 . Object ) ;
287+ ConfigurationClientWrapper cw2 = new ConfigurationClientWrapper ( TestHelpers . SecondaryConfigStoreEndpoint , mockClient2 . Object ) ;
288+
289+ var clientList = new List < ConfigurationClientWrapper > ( ) { cw1 , cw2 } ;
290+ var configClientManager = new ConfigurationClientManager ( clientList ) ;
291+
292+ var config = new ConfigurationBuilder ( )
293+ . AddAzureAppConfiguration ( options =>
294+ {
295+ options . ClientManager = configClientManager ;
296+ options . Select ( "TestKey*" ) ;
297+ options . ConfigureRefresh ( refreshOptions =>
298+ {
299+ refreshOptions . Register ( "TestKey1" , "label" )
300+ . SetCacheExpiration ( TimeSpan . FromSeconds ( 1 ) ) ;
301+ } ) ;
302+
303+ refresher = options . GetRefresher ( ) ;
304+ } )
305+ . Build ( ) ;
306+
307+ // The client enumerator should return just 1 client.
308+ Assert . Single ( configClientManager . GetAvailableClients ( DateTimeOffset . UtcNow ) ) ;
309+
310+ // The build should be successful since one client was backed off and it failed over to the second client.
311+ Assert . Equal ( "TestValue1" , config [ "TestKey1" ] ) ;
312+ }
260313 }
261314}
0 commit comments