如何对该功能进行单元测试

时间:2020-03-08 09:20:54

标签: c# unit-testing

我有办法。我想用单元测试来测试方法。什么是测试该方法的好方法?

public class ChoiceOption
    {
        public static int Choice(string message, string errorMessage)
        {
            while (true)
            {
                try
                {
                    Console.Write(message);
                    string userInput = Console.ReadLine();
                    if (userInput == string.Empty)
                    {
                        userInput = "0";
                    }
                    return int.Parse(userInput);
                }
                catch (Exception)
                {
                    Console.WriteLine(errorMessage);
                }
            }
        }
    }

3 个答案:

答案 0 :(得分:2)

首先,重写您的方法,使其可以进行单元测试,并且不依赖于控制台的输入和输出,例如

public class ChoiceOption
{
    private readonly Func<string> readLine;
    private readonly Action<string> writeLine;

    public ChoiceOption(Func<string> readLine, Action<string> writeLine)
    {
        this.readLine = readLine;
        this.writeLine = writeLine;
    }

    public int Choice(string message, string errorMessage)
    {
        while (true)
        {
            writeLine(message);
            string userInput = readLine();
            if (string.IsNullOrEmpty(userInput)) return 0;
            if (int.TryParse(userInput, out int result))
            {
                return result;
            }
            writeLine(errorMessage);
        }
    }
}

现在,您可以注入用于读取和写入行的方法,以注入测试数据并收集输出以进行检查。看看nuget软件包Moq,它也是创建那些模拟对象进行测试的方式。

[TestFixture]
public class TestMethod
{
    [TestCase("", ExpectedResult = "Message\n0")]
    [TestCase("123", ExpectedResult = "Message\n123")]
    [TestCase("A\n1234", ExpectedResult = "Message\nError\nMessage\n1234")]
    public string MethodReturnsExpected(string input)
    {
        // Create mock objects for testing that simulate user input
        int readPos = 0;
        string output = "";
        Func<string> readline = () => input.Split('\n')[readPos++];
        Action<string> writeline = (line) => output = output + line + "\n";

        // Create the 'unit under test'
        var uut = new ChoiceOption(readline, writeline);

        int result = uut.Choice("Message", "Error");

        // Return something that can be verified
        return output + result;
    }
}

答案 1 :(得分:1)

首先,您应该将方法更改为pure function,以简化测试(例如,不进行模拟等),因此您需要在方法之外提取用户输入,并且理想情况下还需要打印到控制台。现在,您可以模拟测试中的用户输入,并声明异常:

public class ChoiceOption
{
    public static int Choice(string userInput, string message, string errorMessage)
    {
        if (userInput == string.Empty)
        {
            userInput = "0";
        }
        return int.Parse(userInput);
    }
}

现在,它很容易测试。循环,用户输入和捕获异常将在此方法的调用程序中。这是您的生产代码,也是单元测试。

答案 2 :(得分:0)

首先应涵盖的是预期的“正确”情况。在这种情况下,它将是几个数字(可能为0,正数和负数)。

此时,您可以尝试一些极端情况:

  • “你好”

  • 'c'

  • 2.5

  • 2 ^ 63

  • true

  • “”

这些是我能想到的直接例子,但最终您的单元测试和您的创造力一样强大