-2

While writing unit tests to Azure Functions how to set Environment variables?

Below is a given sample code where the original function gets SQL connection string from the Environment variables using key sqldb_conn.

namespace LoanData.API
{
    public static class LoanFunction
    {

        [FunctionName("get-loan")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation($"C# HTTP trigger function executed at: {DateTime.Now}");

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            List<Models.Loan> loan = new List<Models.Loan>();

            var SqlConnStr = Environment.GetEnvironmentVariable("sqldb_conn");

            try
            {
                String commandText = "SELECT * FROM [dhub_data].[LOAN_INFO_V2]";
                using (SqlDataReader reader = Utils.SQLHelper.ExecuteReader(SqlConnStr, commandText, CommandType.Text, null))
                {
                    if (!reader.HasRows)
                    {
                        log.LogInformation("No data returned");
                    }

                    while (reader.Read())
                    {
                        Models.Loan loan = new Models.Loan();
                        loan.ID =  SQLReaderExtensions.SafeGetString(reader, "ID");
                        loan.NAME = SQLReaderExtensions.SafeGetString(reader, "NAME");
                        loan.LAST_UPDATE_DATE = SQLReaderExtensions.SafeGetString(reader, "LAST_UPDATE_DATE");
                        loan.CREATED_BY = SQLReaderExtensions.SafeGetString(reader, "CREATED_BY");
                        loan.CREATION_DATE = SQLReaderExtensions.SafeGetString(reader, "CREATION_DATE");
                        loanResponse.Add(loan);
                        log.LogInformation(loan.ToString());
                    }
                    reader.Close();
                }

                if (loanResponse.Count > 0)
                {
                    return new OkObjectResult(loanResponse);
                }
                else
                {
                    return new NotFoundResult();
                }
            }
            catch (Exception ex)
            {
                log.LogError(ex.Message);
                return new BadRequestObjectResult(ex.Message);
            }
        }
    }
}

Here is the sample test code written for the above Azure Function:

[Fact]
public async void Http_trigger_should_return_known_string()
{
    var request = TestFactory.CreateHttpRequest("name", "Bill");
    var response = (OkObjectResult)await HttpTrigger.Run(request, logger);
    Assert.Equal("Hello, Bill", response.Value);
}

How do I modify this to suit my function? Following https://learn.microsoft.com/en-us/azure/azure-functions/functions-test-a-function

Nazim
  • 639
  • 2
  • 10
  • 26
Josh
  • 89
  • 9
  • Your original question was how to set Environment Variable, that is why I answered with a solution. You updated your question and removed that part. Please keep your original question even if you are editing you original question. You can add new parts with EDIT tag. In order to able to test your code, you have to follow SOLID principles. On your code you are calling static method which opens database connection and execute reader. It is better to separate your Data Access logic and inject it to your Azure Functions so that you can test it. – Nazim Apr 09 '20 at 19:48
  • Hi Nazim. Thanks for your answer. I was trying to post my question. I was having some issues with editing and posting the updated question. I had to truncate portion of the my question. Sorry about it, – Josh Apr 09 '20 at 20:05

1 Answers1

2

You can set it manually as below on your unit test:

Environment.SetEnvironmentVariable("key", "value");
Nazim
  • 639
  • 2
  • 10
  • 26
  • It is because you are getting BadRequest from your HttpTrigger.Run method and you are trying to cast it to OkObjectResult. You can debug your run method while testing, check where is the BadRequest coming from. – Nazim Apr 09 '20 at 19:41
  • Thanks Nazim for your reply. This is my first function and was trying to write unit test. – Josh Apr 09 '20 at 19:53
  • That is absolutely fine, hope you good learning on Azure Functions. Do you still have any outstanding questions? – Nazim Apr 09 '20 at 20:09
  • Hi Nazim, Yes I do have questions. In your previous post you mentioned that It is better to separate your Data Access logic and inject it to your Azure Functions so that you can test it. I am having several functions in one function app. So I just have the logic to open the connection and return the reader in a helper class.I am formatting the response in the function and returning it. How can I do it in a better way? Appreciate your help – Josh Apr 09 '20 at 20:19
  • You can use this link https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection to inject your services to your Azure Functions. You should create a separate project which does Database operations. I advise using a Repository Pattern with Entity Framework. On that project, you can define your interfaces and inject those interfaces to your Functions. As a result, you can mock this interface while testing your functions. – Nazim Apr 09 '20 at 20:43
  • Thanks Nazim. I will look into it. I posted an other question https://stackoverflow.com/questions/61129970/azure-function-portal-code-deployment-feature-is-skipping-build Is this something you have done? – Josh Apr 09 '20 at 21:02
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/211318/discussion-between-josh-and-nazim). – Josh Apr 09 '20 at 21:07