By Randy Randalf


2019-04-15 11:05:06 8 Comments

I need to mock the endpoint of the Key Vault in order to know if I am calling the function to get the key vault once.

I am developing this with C# and Moq (Framework) in order to do the testing.

The interface is the following:

public interface IKeyVaultConnection
{
    string GetKeyVaultValue(string variableName);
}
 public class KeyVaultConnection
    {
        public KeyVaultClient keyVaultClient;
        private string endpointKeyVault;

        public KeyVaultConnection(string keyVaultAddress = "DefaultEndpoint")
        {
            AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
            keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
            endpointKeyVault = $"https://{ keyVaultAddress }.vault.azure.net";
        }

        private async Task<string> AsyncGetSecretValue(string keyName)
        {
            var secret = await keyVaultClient.GetSecretAsync($"{endpointKeyVault}/secrets/{ keyName }")
                    .ConfigureAwait(false);

            return secret.Value;
        }

        public string GetKeyVaultValue(string variableName)
        {
            Task<string> task = Task.Run(async () => await AsyncGetSecretValue(variableName));
            task.Wait();
            return task.Result;
        }
}

 Mock<IKeyVaultConnection> mock = new Mock<IKeyVaultConnection>();
//----->>>>>>   Need to setup the endpoint
 mock.Setup(x => x.GetKeyVaultValue(It.IsAny<string>())).Returns(It.IsAny<string>());
 // mock.Verify(x => x.GetKeyVaultValue(It.IsAny<string>()), Times.Once());

What I need is to fake the connection to the endpoint in order to get that I am calling that function once and I am getting errors like:

"KeyVaultErrorException: Operation returned an invalid status code 'NotFound'"

for not providing the endpoint.

If I uncomment last line (mock.Verify(x => x.GetKeyVaultValue(It.IsAny<string>()), Times.Once());) I get this:

"Expected invocation on the mock once, but was 0 times: 
 x => x.GetKeyVaultValue(It.IsAny<string>())"

1 comments

@Scott Hannen 2019-04-15 16:42:19

If you view your class as nothing but a humble wrapper so that other classes can depend on ISomethingThatReturnsValues without knowing about KeyVaultClient then mocking KeyVaultClient isn't necessary. We only need to go so far. We don't need to unit test framework classes that we depend on.

In other words, do we need to verify that

keyVaultClient.GetSecretAsync($"{endpointKeyVault}/secrets/{ keyName }")

...actually calls the endpoint to get the secret? It does. That's what KeyVaultClient.GetSecretAsync(string) does. If the test fails, what can we do? We can't fix that class. Similarly, if we followed that road to its logical conclusion, we'd have to test all sorts of stuff. When we create a List<string> and add a string, does it really get added? We don't test those things because they're already tested so it's reasonable to assume that they work as expected.

A good test for this would be an integration test which verifies that your class does what it expected. Or, if another class depends on this, you could write an integration test for that class which would fail if you can't retrieve anything from the key vault. But that wouldn't require any mocking.

Part of being comfortable with not unit testing the class is minimizing it so that it really does nothing except invoke the inner class. In this case you could collapse your public and private method into one public method, and maybe one more to provide an async option:

    public async Task<string> GetSecretValueAsync(string keyName)
    {
        return await keyVaultClient.GetSecretAsync($"{endpointKeyVault}/secrets/{ keyName }");
    }

    public string GetSecretValue(string keyName) => GetSecretValueAsync(keyName).Result;

Now it's more evident: This class doesn't really do anything of its own that needs unit testing. Its useful purpose is to adapt KeyVaultClient to your interface - IKeyVaultConnection so that other classes don't directly depend on KeyVaultClient.

Related Questions

Sponsored Content

25 Answered Questions

[SOLVED] How should I unit test threaded code?

48 Answered Questions

21 Answered Questions

[SOLVED] What is Unit test, Integration Test, Smoke test, Regression Test?

31 Answered Questions

[SOLVED] Unit Testing C Code

13 Answered Questions

[SOLVED] JavaScript unit test tools for TDD

12 Answered Questions

[SOLVED] Unit test naming best practices

5 Answered Questions

[SOLVED] How to verify that method was NOT called in Moq?

  • 2009-02-11 15:24:21
  • alex
  • 62245 View
  • 421 Score
  • 5 Answer
  • Tags:   c# .net moq

30 Answered Questions

44 Answered Questions

[SOLVED] Is Unit Testing worth the effort?

  • 2008-09-15 21:44:00
  • Ross Fuhrman
  • 266546 View
  • 573 Score
  • 44 Answer
  • Tags:   unit-testing

1 Answered Questions

[SOLVED] Using Moq to mock an asynchronous method for a unit test

Sponsored Content