Skip to content

[Identity] Add background token refresh to async creds

80497f5
Select commit
Loading
Failed to load commit list.
Draft

Add background token refresh to async creds #47169

[Identity] Add background token refresh to async creds
80497f5
Select commit
Loading
Failed to load commit list.
Azure Pipelines / python - pullrequest failed May 27, 2026 in 23m 29s

Build #20260527.51 had test failures

Details

Tests

  • Failed: 46 (0.11%)
  • Passed: 38,718 (95.05%)
  • Other: 1,969 (4.83%)
  • Total: 40,733

Annotations

Check failure on line 6927 in Build log

See this annotation in the file changed.

@azure-pipelines azure-pipelines / python - pullrequest

Build log #L6927

PowerShell exited with code '1'.

Check failure on line 64773 in Build log

See this annotation in the file changed.

@azure-pipelines azure-pipelines / python - pullrequest

Build log #L64773

There are one or more test failures detected in result files. Detailed summary of published test results can be viewed in the Tests tab.

Check failure on line 4639 in Build log

See this annotation in the file changed.

@azure-pipelines azure-pipelines / python - pullrequest

Build log #L4639

PowerShell exited with code '1'.

Check failure on line 69568 in Build log

See this annotation in the file changed.

@azure-pipelines azure-pipelines / python - pullrequest

Build log #L69568

There are one or more test failures detected in result files. Detailed summary of published test results can be viewed in the Tests tab.

Check failure on line 1 in test_retry_delay[get_token]

See this annotation in the file changed.

@azure-pipelines azure-pipelines / python - pullrequest

test_retry_delay[get_token]

AssertionError: Expected 'mock' to be called once. Called 2 times.
Calls: [call('scope', claims=None, tenant_id=None, enable_cae=False),
 call('scope', claims=None, tenant_id=None, enable_cae=False)].
Raw output
get_token_method = 'get_token'

    @pytest.mark.parametrize("get_token_method", GET_TOKEN_METHODS)
    async def test_retry_delay(get_token_method):
        """A credential should wait between requests when trying to refresh a token"""
    
        now = time.time()
        credential = MockCredential(cached_token=AccessTokenInfo(CACHED_TOKEN, int(now + DEFAULT_REFRESH_OFFSET - 1)))
    
        # the credential should swallow exceptions during proactive refresh attempts
        credential.request_token = mock.Mock(side_effect=Exception("whoops"))
        for i in range(4):
            token = await getattr(credential, get_token_method)(SCOPE)
            assert token.token == CACHED_TOKEN
            credential.acquire_token_silently.assert_called_with(SCOPE, claims=None, enable_cae=False, tenant_id=None)
>           credential.request_token.assert_called_once_with(SCOPE, claims=None, enable_cae=False, tenant_id=None)

tests/test_get_token_mixin_async.py:142: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Mock id='139763910104864'>, args = ('scope',)
kwargs = {'claims': None, 'enable_cae': False, 'tenant_id': None}
msg = "Expected 'mock' to be called once. Called 2 times.\nCalls: [call('scope', claims=None, tenant_id=None, enable_cae=False),\n call('scope', claims=None, tenant_id=None, enable_cae=False)]."

    def assert_called_once_with(self, /, *args, **kwargs):
        """assert that the mock was called exactly once and that that call was
        with the specified arguments."""
        if not self.call_count == 1:
            msg = ("Expected '%s' to be called once. Called %s times.%s"
                   % (self._mock_name or 'mock',
                      self.call_count,
                      self._calls_repr()))
>           raise AssertionError(msg)
E           AssertionError: Expected 'mock' to be called once. Called 2 times.
E           Calls: [call('scope', claims=None, tenant_id=None, enable_cae=False),
E            call('scope', claims=None, tenant_id=None, enable_cae=False)].

/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/unittest/mock.py:940: AssertionError

Check failure on line 1 in test_retry_delay[get_token_info]

See this annotation in the file changed.

@azure-pipelines azure-pipelines / python - pullrequest

test_retry_delay[get_token_info]

AssertionError: Expected 'mock' to be called once. Called 2 times.
Calls: [call('scope', claims=None, tenant_id=None, enable_cae=False),
 call('scope', claims=None, tenant_id=None, enable_cae=False)].
Raw output
get_token_method = 'get_token_info'

    @pytest.mark.parametrize("get_token_method", GET_TOKEN_METHODS)
    async def test_retry_delay(get_token_method):
        """A credential should wait between requests when trying to refresh a token"""
    
        now = time.time()
        credential = MockCredential(cached_token=AccessTokenInfo(CACHED_TOKEN, int(now + DEFAULT_REFRESH_OFFSET - 1)))
    
        # the credential should swallow exceptions during proactive refresh attempts
        credential.request_token = mock.Mock(side_effect=Exception("whoops"))
        for i in range(4):
            token = await getattr(credential, get_token_method)(SCOPE)
            assert token.token == CACHED_TOKEN
            credential.acquire_token_silently.assert_called_with(SCOPE, claims=None, enable_cae=False, tenant_id=None)
>           credential.request_token.assert_called_once_with(SCOPE, claims=None, enable_cae=False, tenant_id=None)

tests/test_get_token_mixin_async.py:142: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Mock id='139763908913248'>, args = ('scope',)
kwargs = {'claims': None, 'enable_cae': False, 'tenant_id': None}
msg = "Expected 'mock' to be called once. Called 2 times.\nCalls: [call('scope', claims=None, tenant_id=None, enable_cae=False),\n call('scope', claims=None, tenant_id=None, enable_cae=False)]."

    def assert_called_once_with(self, /, *args, **kwargs):
        """assert that the mock was called exactly once and that that call was
        with the specified arguments."""
        if not self.call_count == 1:
            msg = ("Expected '%s' to be called once. Called %s times.%s"
                   % (self._mock_name or 'mock',
                      self.call_count,
                      self._calls_repr()))
>           raise AssertionError(msg)
E           AssertionError: Expected 'mock' to be called once. Called 2 times.
E           Calls: [call('scope', claims=None, tenant_id=None, enable_cae=False),
E            call('scope', claims=None, tenant_id=None, enable_cae=False)].

/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/unittest/mock.py:940: AssertionError

Check failure on line 1 in test_retry_delay[get_token]

See this annotation in the file changed.

@azure-pipelines azure-pipelines / python - pullrequest

test_retry_delay[get_token]

AssertionError: Expected 'mock' to be called once. Called 2 times.
Calls: [call('scope', claims=None, tenant_id=None, enable_cae=False),
 call('scope', claims=None, tenant_id=None, enable_cae=False)].
Raw output
get_token_method = 'get_token'

    @pytest.mark.parametrize("get_token_method", GET_TOKEN_METHODS)
    async def test_retry_delay(get_token_method):
        """A credential should wait between requests when trying to refresh a token"""
    
        now = time.time()
        credential = MockCredential(cached_token=AccessTokenInfo(CACHED_TOKEN, int(now + DEFAULT_REFRESH_OFFSET - 1)))
    
        # the credential should swallow exceptions during proactive refresh attempts
        credential.request_token = mock.Mock(side_effect=Exception("whoops"))
        for i in range(4):
            token = await getattr(credential, get_token_method)(SCOPE)
            assert token.token == CACHED_TOKEN
            credential.acquire_token_silently.assert_called_with(SCOPE, claims=None, enable_cae=False, tenant_id=None)
>           credential.request_token.assert_called_once_with(SCOPE, claims=None, enable_cae=False, tenant_id=None)

tests/test_get_token_mixin_async.py:142: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Mock id='140130342894560'>, args = ('scope',)
kwargs = {'claims': None, 'enable_cae': False, 'tenant_id': None}
msg = "Expected 'mock' to be called once. Called 2 times.\nCalls: [call('scope', claims=None, tenant_id=None, enable_cae=False),\n call('scope', claims=None, tenant_id=None, enable_cae=False)]."

    def assert_called_once_with(self, /, *args, **kwargs):
        """assert that the mock was called exactly once and that that call was
        with the specified arguments."""
        if not self.call_count == 1:
            msg = ("Expected '%s' to be called once. Called %s times.%s"
                   % (self._mock_name or 'mock',
                      self.call_count,
                      self._calls_repr()))
>           raise AssertionError(msg)
E           AssertionError: Expected 'mock' to be called once. Called 2 times.
E           Calls: [call('scope', claims=None, tenant_id=None, enable_cae=False),
E            call('scope', claims=None, tenant_id=None, enable_cae=False)].

/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/unittest/mock.py:940: AssertionError

Check failure on line 1 in test_retry_delay[get_token_info]

See this annotation in the file changed.

@azure-pipelines azure-pipelines / python - pullrequest

test_retry_delay[get_token_info]

AssertionError: Expected 'mock' to be called once. Called 2 times.
Calls: [call('scope', claims=None, tenant_id=None, enable_cae=False),
 call('scope', claims=None, tenant_id=None, enable_cae=False)].
Raw output
get_token_method = 'get_token_info'

    @pytest.mark.parametrize("get_token_method", GET_TOKEN_METHODS)
    async def test_retry_delay(get_token_method):
        """A credential should wait between requests when trying to refresh a token"""
    
        now = time.time()
        credential = MockCredential(cached_token=AccessTokenInfo(CACHED_TOKEN, int(now + DEFAULT_REFRESH_OFFSET - 1)))
    
        # the credential should swallow exceptions during proactive refresh attempts
        credential.request_token = mock.Mock(side_effect=Exception("whoops"))
        for i in range(4):
            token = await getattr(credential, get_token_method)(SCOPE)
            assert token.token == CACHED_TOKEN
            credential.acquire_token_silently.assert_called_with(SCOPE, claims=None, enable_cae=False, tenant_id=None)
>           credential.request_token.assert_called_once_with(SCOPE, claims=None, enable_cae=False, tenant_id=None)

tests/test_get_token_mixin_async.py:142: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Mock id='140130338492704'>, args = ('scope',)
kwargs = {'claims': None, 'enable_cae': False, 'tenant_id': None}
msg = "Expected 'mock' to be called once. Called 2 times.\nCalls: [call('scope', claims=None, tenant_id=None, enable_cae=False),\n call('scope', claims=None, tenant_id=None, enable_cae=False)]."

    def assert_called_once_with(self, /, *args, **kwargs):
        """assert that the mock was called exactly once and that that call was
        with the specified arguments."""
        if not self.call_count == 1:
            msg = ("Expected '%s' to be called once. Called %s times.%s"
                   % (self._mock_name or 'mock',
                      self.call_count,
                      self._calls_repr()))
>           raise AssertionError(msg)
E           AssertionError: Expected 'mock' to be called once. Called 2 times.
E           Calls: [call('scope', claims=None, tenant_id=None, enable_cae=False),
E            call('scope', claims=None, tenant_id=None, enable_cae=False)].

/opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/unittest/mock.py:940: AssertionError