Search code examples
c#.netvisual-studiounit-testingxunit

How to test Process ExitCode value


I have a mechanism to kill process in some circumstances. Given *.exe requires *.dll's. Everything works fine in production and in NCrunch (if "Copy referenced assemblies to workspace" setting is set to true). Unfortunatelly I can't get it to work in VisualStudio Test Explorer.

My test crashes right after start. I expect specific ExitCode with defined meaning but I always get -532462766.

enter image description here

I start my proces based on Assembly location:

enter image description here

It's about DLLs. System logs confirm that files are missing.

enter image description here

enter image description here

If I capture Console it confirms that it is about missing DLLs. Of course in real scenario no console/form/windows pops, thats just in simplified solution.

enter image description here

I have checked given temp location created by test tool and I have noticed that *.exe is in different subfolder than DLLs. I guess *.exe does not know how to reference to them as they are not in their usual relative location. NCrunch keeps all files in main temp directory that's why it is working.

How can I test it? I don't want to create Environment wrapper to mock it. I wan't to trully test if Process starts and is able to kill itself if some specific conditions are met.

Here is super-siplified version of my project:

enter image description here

Main project (ExternalProcess)


namespace ExternalProcess {
    public class Program {
        public static void Main(string[] args) {

            CommonCode.Enums.ProcessType processType = (CommonCode.Enums.ProcessType)Enum.Parse(typeof(CommonCode.Enums.ProcessType), args[0]);

            switch (processType) {
                case CommonCode.Enums.ProcessType.TEST:
                case CommonCode.Enums.ProcessType.PROD:
                case CommonCode.Enums.ProcessType.DEV:
                    Environment.Exit((int)processType);
                    break;
                default:
                    Environment.Exit((int)CommonCode.Enums.ProcessType.ERROR);
                    break;
            }
        }
    }
}

Additional DLL (ExternalProcess.CommonCode)

namespace ExternalProcess.CommonCode.Enums {
    public enum ProcessType {

        PROD,
        TEST,
        DEV,
        ERROR
    }
}

Test Project (ExternalProcessTests)

using System.Reflection;
using FluentAssertions;
using Xunit;

namespace ExternalProcessTests {
    public class ProcessTests {

        [Fact]
        public void TestProcess() {

            var processType = ExternalProcess.CommonCode.Enums.ProcessType.TEST;

            var process = new System.Diagnostics.Process {
                EnableRaisingEvents = false
            };

            process.StartInfo.FileName = Assembly.GetAssembly(typeof(ExternalProcess.Program)).Location;
            process.StartInfo.UseShellExecute = true;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.Arguments = processType.ToString();

            process.Start();

            process.WaitForExit();

            process.HasExited.Should().BeTrue();
            process.ExitCode.Should().Be((int)processType);
        }
    }
}

Solution

  • You can use

     process.StartInfo.FileName = Assembly.GetAssembly(typeof(ExternalProcess.Program)).CodeBase;
    

    instead. It works for me.