I have some code that I'd like to unit test.
I am retrieving some data from an Azure Storage Table database as part of my method that I'd like to test, so I need to mock out the return from the database.
Code to test:
public class GetCustomer : IGetCustomer
{
//constructor
public GetCustomer(IClientTableFactory clientTableFactory)
{
_partitionKey = "test";
_customersTable = clientTableFactory.GetStorageTable("customers");
}
//method to test
public async Task<string> GetCustomerNameAsync(string email)
{
//match on full email
var match = await SearchAsync(email.ToLower());
if (match == null)
{
//just match on email domain
var domain = email.ToLower().Substring(email.IndexOf("@"));
match = await SearchAsync(domain);
}
return match;
}
//internal method that queries Azure Table Storage
private async Task<string> SearchAsync(string searchString)
{
var query = TableOperation.Retrieve<Customer>(_partitionKey, rowkey: searchString);
var result = await _customersTable.ExecuteAsync(query);
var match = result.Result as Customer;
return match?.Name;
}
}
Unit Test so far:
//Arrange
var email = "Testy.McTest@Test.com.au";
var tableFactory = new Mock<IClientTableFactory>();
var customersTable = new Mock<CloudTable>(new Uri("http://unittests.localhost.com/FakeTable"));
customersTable.Setup(x => x.ExecuteAsync(It.IsAny<TableOperation>()))
.ReturnsAsync(new TableResult{ HttpStatusCode = 200, Result = new Customer{ Name = "jiminy crickets" }});
tableFactory.Setup(x => x.GetStorageTable("customers")).Returns(customersTable.Object);
var getCustomers = new GetCustomer(tableFactory.Object);
// Act
var result = await getCustomers.GetCustomerNameAsync(email);
// Assert
Assert.AreEqual("jiminy crickets", result);
Of course, the test passes every time. The missing piece of the puzzle that I would like to mock out is this line:
customersTable
.Setup(x => x.ExecuteAsync(It.IsAny<TableOperation>()))
.ReturnsAsync...
I should be able to replace It.IsAny<TableOperation>() with my search query eg It.Is<TableOperation>(y => y.RowKey == "testy.mctest@test.com.au" but unfortunately RowKey is inaccessible.
I've also tried
customersTable
.Setup(x => x.ExecuteAsync(TableOperation.Retrieve<Customer>(_partitionKey, rowkey: searchString))
but it never passes this code at runtime - maybe because of the ETag property?
Any ideas? I've seen plenty of answers about mocking Table Storage, but none about mocking Query results.