Search code examples
c#testingprogram-entry-pointxunit

Unit testing: try statement in program.cs Main


I have my project that starts like below. I want to create a unit test to validate what happens when either appsetting.Environment.json doesn't exist or the DataSource:JsonPath file doesn't exist.

I am using xUnit but just getting into it,

With this scenario it should throw a FileNotFoundException and exit.

internal class Program
{
    private static int Main(string[] args)
    {
        public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ENVIRONMENT") ?? "Production"}.json", optional: true)
            .Build();

        try
        {
            Log.Information($"{DateTime.Now.ToLongTimeString()} Starting...");

            var jsonFileName = Configuration["DataSource:JsonPath"];
            if (!File.Exists(jsonFileName)) throw new FileNotFoundException(jsonFileName);

            //code if file exist...
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Terminated unexpectedly");
            return 1;
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }
}

Solution

  • Without changing any of your code, there are two ways to do this:

    • Actually run the program using the Process class and examine the exit code of your program (exposed in the Process.ExitCode property). In this case, the fact that the class is internal and the Main is private doesn't matter.

    • Use reflection to get ahold of the Main method and invoke it, examining the return value.

    If none of those are palatable, you can change your Main to internal and use the [InternalsVisibleTo] attribute to enable your unit test to call that method without reflection.

    For all 3 of these cases your test passes if the exit code is 0 and fails if the exit code is 2 (assuming there are no other possible exit codes).