加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 单元测试服务完全依赖于第三方应用程序

发布时间:2020-12-16 00:17:33 所属栏目:百科 来源:网络整理
导读:我目前正在C#中编写一个 Windows服务,负责托管WCF服务.调用Service Operations时,我的服务将执行命令行应用程序,对StandardOutput执行一些数据处理并返回结果.此命令行应用程序更改服务器上其他第三方服务的状态. 这是一个罕见的例子,我真的能够从头开始,所
我目前正在C#中编写一个 Windows服务,负责托管WCF服务.调用Service Operations时,我的服务将执行命令行应用程序,对StandardOutput执行一些数据处理并返回结果.此命令行应用程序更改服务器上其他第三方服务的状态.

这是一个罕见的例子,我真的能够从头开始,所以我想以一种可以轻松进行单元测试的方式正确设置它.没有遗留代码,所以我有一个干净的名单.我正在努力的是如何使我的服务单元可测试,因为它几乎完全依赖于外部应用程序.

我的服务操作与命令行应用程序的操作大致成1:1的比例.如果您还没有猜到,我正在构建一个工具,允许远程管理仅提供CLI管理的服务.

这只是一个单元测试比它们值得更麻烦的情况吗?为了提供一些上下文,这里是我的概念验证应用程序的快速示例.

private string RunAdmin(String arguments)
    {
        try
        {
            var exe = String.Empty;
            if (System.IO.File.Exists(@"C:Program Files (x86)Appadmin.exe"))
            {
                exe = @"C:Program Files (x86)Appadmin.exe";
            }
            else
            {
                exe= @"C:Program FilesAppadmin.exe";
            }

            var psi = new System.Diagnostics.ProcessStartInfo
            {
                FileName = exe,UseShellExecute = false,RedirectStandardInput = true,RedirectStandardOutput = true,};

            psi.Arguments = String.Format("{0} -u {1} -p {2} -y",arguments,USR,PWD);

            var adm= System.Diagnostics.Process.Start(psi);

            var output = fmsadmin.StandardOutput.ReadToEnd();

            return output;
        }
        catch (Exception ex)
        {
            var pth = 
                System.IO.Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.Desktop),"FMSRunError.txt");

            System.IO.File.WriteAllText(pth,String.Format("Message:{0}rnrnStackTrace:{1}",ex.Message,ex.StackTrace));

            return String.Empty;
        }
    }

    public String Restart()
    {
        var output = this.RunAdmin("/restart");
        return output; // has cli tool return code
    }

如果不向我的RunAdmin方法添加大量“测试”代码,有没有办法对其进行单元测试?显然我可以在RunAdmin方法中添加大量代码来“伪造”输出,但我想尽可能避免这种情况.如果这是推荐的方式,我可以为自己创建一个脚本来创建所有可能的输出.还有另外一种方法吗?

解决方法

IMO提出了一种测试你正在编写的代码的方法,并不会比它的价值更麻烦.通过良好的测试可以更轻松地使用新功能,修复错误并维护应用程序.根据您所描述的内容,我认为您需要确定哪种测试更适合您的情况:单元测试或集成测试.

如果要编写真正的单元测试,那么您将不得不抽象出命令行工具,这样您就可以针对一个实体编写测试,该实体将始终为您的请求返回相同的预期响应.如果创建一个接口来将调用包装到命令行工具,那么您可以轻松地模拟响应.如果您使用这种方法,那么重要的是要记住您正在测试的是您的服务按预期响应命令行工具的输出.您必须伪造命令行工具可能发出的所有潜在响应.显然,如果输出非常复杂,那么这可能不是一个选择.如果您认为可以伪造答案,那么请看一下那里的一些模拟框架(我喜欢Moq).他们将使工作更容易.

另一种方法是使用集成测试.这些测试将依赖于运行命令行工具的服务,并检查服务返回的实际响应.以这种方式进行测试很可能需要您有办法将正在测试的机器重置回其原始状态,假设命令行应用程序实际上将对该机器进行更改.根据我的经验,这些测试通常会运行得更慢并且更难以维护.但是,如果从命令行工具返回的数据太难以伪造,那么集成测试是一种可行的方法.

另一种方法,也许是我应该使用的方法,是使用两者.当命令行工具很容易伪造时,使用单元测试.如果不是,请使用集成测试.对于我的项目,我非常喜欢能够编写不依赖外部任何东西的真正单元测试.不幸的是,由于我必须处理许多旧代码,因此并非总是可行.然而,即使是我总是感觉更好,如果我可以对整个事情进行高级集成测试,只需增加一点覆盖率.例如,如果我正在编写一个网站,我可能会有100个单元测试,涵盖了构建网页的所有细节,但如果可以,我将进行1或2个集成测试来构建网页请求和检查页面上的文字,只是为了理智.拥有这两种类型的测试肯定会让我对代码在上线时按预期工作的信心更高.

希望有所帮助.

编辑
我正在考虑这个问题,并且可能有一种相对简单的方法来处理应用程序的单元测试.要伪造命令行工具的输入,只需运行命令行工具,以适用于您要测试的任何方案.将输出保存为文本文件,然后使用该文本文件作为测试的输入.如果使用接口和依赖注入,则无论您是运行测试还是实际应用程序,服务代码都是相同的.例如,假设我们正在测试一个打印出CLI版本号的方法:

public interface ICommandLineRunner
{
    string RunCommand(string command);
}

public class CLIService
{
   private readonly ICommandLineRunner _cliRunner;
   public CLIService(ICommandLineRunner cliRunner)
   {
       _cliRunner = cliRunner;
   }

   public string GetVersionNumber()
   {
       string output = _cliRunner.RunCommand("-version");
       //Parse output and store in result
       return result;        
   }
}

[Test]
public void Test_Gets_Version_Number()
{
    var mockCLI = new Mock<ICommandLineRunner>();
    mockCLI.Setup(a => a.RunCommand(It.Is<string>(s => s == "-version"))
       .Returns(File.ReadAllText("version-number-output.txt"));

    var mySvc = new CLIService(mockCLI.Object);
    var result = mySvc.GetVersionNumber();
    Assert.AreEqual("1.0",result);
}

在这种情况下,我们将ICommandLineRunner注入到CLIService中,我们正在模拟对RunCommand的调用,以返回我们事先设置的特定输出(我们的文本文件的内容).这种方法允许我们测试CLIService是否正确调用ICommandLineRunner,并且它正确地解析了该调用的输出.如果您需要我澄清有关此方法的任何信息,请告诉我.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读