Technology Stack
- DBUP for DB upgrades
- Azure Durable for activities
- Rhino mocks for unit testing.
Situation
Currently, I have placed my DB Upgrade (DBUp) statements in the HTTPStart method as its the entry point of my durable azure function.
DeployChanges.To
.SqlDatabase(connectionString)
.WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly())
.LogToConsole()
.Build();
Problem
Problem with this approach is that DBUp uses a static class to upgrade DB and I can't use Rhino to mock methods on a static class.
Question
I thought of wrapping the DBUp part in a non-static class but then I would need to mock constructor initialization. Not sure if this would work
Code - Helper Class which upgrades DB
public class DBUPHelper
{
public bool UpgradeDB()
{
bool status = true;
var connectionString = "Data Source=localhost;Initial Catalog=master;Integrated Security=True;Connect Timeout=15";
var upgrader =
DeployChanges.To
.SqlDatabase(connectionString)
.WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly())
.LogToConsole()
.Build();
var result = upgrader.PerformUpgrade();
if (!result.Successful)
{
status = false;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(result.Error);
Console.ResetColor();
}
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Success!");
Console.ResetColor();
return status;
}
}
Code - HTTPStart Method which calls Helper class
private static ILogger logObj;
[FunctionName("HttpStart")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}")] HttpRequestMessage req,
[OrchestrationClient] DurableOrchestrationClientBase starter,
string functionName,
ILogger log, ExecutionContext context)
{
HttpResponseMessage response = null;
var config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
Helper.Helper helper = new Helper.Helper(config.GetConnectionString("ConnString"););
if (helper.UpgradeDB())
{
log.LogInformation("DB Upgraded Successfully");
logObj = log;
try
{
var provider = new MultipartMemoryStreamProvider();
await req.Content.ReadAsMultipartAsync(provider);
Application policy = await GeneratePolicyObject(provider);
string instanceId = await starter.StartNewAsync(functionName, policy);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
response = starter.CreateCheckStatusResponse(req, instanceId);
response.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(10));
}
catch (Exception ex)
{
response = new HttpResponseMessage();
log.LogCritical(ex.ToString());
log.LogCritical(ex.InnerException.ToString());
log.LogCritical(ex.StackTrace);
response.Content = new StringContent(ex.ToString());
response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
}
}
else log.LogCritical("DB Upgrade Failed. Check logs for exception");
return response;
}
See the highlighted area. I want to mock the constructor initialization so that DB calls does not happen while Unit Testing.
Can anyone help, please.
Regards Tarun