Reputation: 87
I have an Azure function that stores applications settings in Azure Blob Storage. To unit test the class that gets and adds the settings, I use moq to have the blob storage abstraction class (blobStorageRepository) throw an exception. It mostly works. however, I have two tests that fail.
I Have other unit tests that mocks the _blobStorageRepository. All work just fine including the test against the "Get" method correctly throws the exception but the "Add" exception tests fail. I've included the actual test below
Fact(DisplayName = "AddUserSettingsAsync - InvalidOperationException")]
[Trait("Category", "Unit Test")]
public async Task SettingsStoreAddUserSettingsTestWithException()
{
string userObject = Guid.NewGuid().ToString();
string correlationId = Guid.NewGuid().ToString();
string body = File.ReadAllText("TestData/userSettings.json");
UserSettingsObject userSettingsObject = JsonConvert.DeserializeObject<UserSettingsObject>(body);
var iFunctionEnvironment = TestHelpers.GetEnvironmentVariable("Test");
Uri.TryCreate("http://localhost", UriKind.Absolute, out Uri uri);
var iblobStorageRepositoryMoq = new Mock<IBlobStorageRepository>();
iblobStorageRepositoryMoq
.Setup(mock => mock.Add(logger, correlationId, body, userObject))
.ThrowsAsync(new Exception("Function Add threw an exception"));
var iblobStorageRepository = iblobStorageRepositoryMoq.Object;
SettingsStore settingsStore = new SettingsStore(iFunctionEnvironment, iblobStorageRepository);
Exception exception = await Assert.ThrowsAsync<InvalidOperationException>(async () => await settingsStore.AddUserSettingsAsync(logger, correlationId, userSettingsObject, userObject));
Assert.Equal("Function Add threw an exception", exception.Message);
Assert.Null(exception.InnerException);
}
Here's the interface for the blogStoreRepository:
Task<bool> Add(ILogger logger, string correlationId, string settingsObject, string settingsObjectName);
Any help would be greatly appreciated!
Upvotes: 1
Views: 3487
Reputation: 247551
If an invoked mock does not behave as expected, most times it is because the setup did not match what was actually invoked.
Consider loosening the expectation using It.IsAny<T>()
Fact(DisplayName = "AddUserSettingsAsync - InvalidOperationException")]
[Trait("Category", "Unit Test")]
public async Task SettingsStoreAddUserSettingsTestWithException() {
//Arrange
string userObject = Guid.NewGuid().ToString();
string correlationId = Guid.NewGuid().ToString();
string body = File.ReadAllText("TestData/userSettings.json");
UserSettingsObject userSettingsObject = JsonConvert.DeserializeObject<UserSettingsObject>(body);
var iFunctionEnvironment = TestHelpers.GetEnvironmentVariable("Test");
Uri.TryCreate("http://localhost", UriKind.Absolute, out Uri uri);
var iblobStorageRepositoryMoq = new Mock<IBlobStorageRepository>();
iblobStorageRepositoryMoq
.Setup(mock => mock.Add(It.IsAny<ILogger>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.ThrowsAsync(new InvalidOperationException("Function Add threw an exception"));
//The SUT
var subjectUnderTest = new SettingsStore(iFunctionEnvironment, iblobStorageRepositoryMoq.Object);
//Act
InvalidOperationException exception = await Assert.ThrowsAsync<InvalidOperationException>(() => subjectUnderTest.AddUserSettingsAsync(logger, correlationId, userSettingsObject, userObject));
//Assert
Assert.Equal("Function Add threw an exception", exception.Message);
Assert.Null(exception.InnerException);
}
Note the change to the setup and also if asserting that InvalidOperationException
was thrown then mock should actually throw an InvalidOperationException
//...
var iblobStorageRepositoryMoq = new Mock<IBlobStorageRepository>();
iblobStorageRepositoryMoq
.Setup(mock => mock.Add(It.IsAny<ILogger>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.ThrowsAsync(new InvalidOperationException("Function Add threw an exception"));
//...
Upvotes: 1