您可以对没有返回类型的void方法进行单元测试吗?

时间:2019-07-07 16:33:06

标签: c# .net unit-testing methods void

我有一个void方法,我想对其进行单元测试,但是不幸的是,我对此没有太多经验。

...

这是我要在其中测试的TestClass,但是在运行它时它会不断加载:

taskrole

2 个答案:

答案 0 :(得分:4)

为测试性正确重构的代码

对这种逻辑进行编码和单元测试的正确方法是:

public class SomeProductionClass 
{
    public string findOccuranceMethod(string str) 
    {
        string occurString = "o";
        string replaceString = "MDDS";
        var array = str.Split(new[] { occurString }, StringSplitOptions.None);
        string result = string.Join(replaceString, array);

        return result;
    }
}

[TestMethod()]
public void findOccuranceMethodTest()
{
    // Arrange
    string expected = "The Haunting MDDSf Hill HMDDSuse!";
    var productionClass = new SomeProductionClass();

    // Act
    var result = productionClass.findOccuranceMethod("The Haunting of Hill House!");

    // Assert
    Assert.AreEqual(expected, result);
}

如何测试原始代码

如果由于某种原因您无法控制生产代码,则有两种选择:

  • 用抽象替换Console

  • 将标准输入/输出重新分配给自定义流:这是最不推荐使用的选项,因为它会使设置/清理更加复杂,并且会干扰测试运行器。

在任何一种情况下,我们都决不能以会为测试/生产引入单独分支的方式修改被测代码。例如,“如果在测试中运行,则执行A,否则执行B” –在这种情况下,我们实际上不是在测试生产代码,而是测试它的另一个分支。

用抽象替换控制台

在这里,我们介绍IConsole来代替System.Console

public interface IConsole
{
    void WriteLine(string s);
    void ReadLine(); // void is enough for this example
}

// for use in production
public class RealConsole : IConsole
{
    public void WriteLine(string s)
    {
        Console.WriteLine(s); 
    }
    public void ReadLine()
    {
        Console.ReadLine();
    }
}

// for use in unit tests
public class TestConsole : IConsole
{
    public void WriteLine(string s)
    {
        Contents.Add(s);
    }
    public void ReadLine()
    {
    }

    public List<string> Contents { get; } = new List<string>();
}

生产代码将保留原始帖子中的内容,只不过现在它使用_console作为依赖项:

public class SomeProductionClass
{
    private readonly IConsole _console;

    public SomeProductionClass(IConsole console)
    {
        _console = console;
    }

    public void findOccuranceMethod()
    {
        string str = "The Haunting of Hill House!";
        _console.WriteLine("String: " + str);
        string occurString = "o";
        string replaceString = "MDDS";

        var array = str.Split(new[] { occurString }, StringSplitOptions.None);
        var count = array.Length - 1;
        string result = string.Join(replaceString, array);

        _console.WriteLine("String after replacing a character: " + result);
        _console.WriteLine("Number of replaces made: " + count);
        _console.ReadLine();
    }
}

,测试代码为:

[TestMethod()]
public void findOccuranceMethodTest()
{
    // Arrange
    string expectedString = "The Haunting MDDSf Hill HMDDSuse!";
    int expectedCount = 2;
    var console = new TestConsole();
    var productionClass = new SomeProductionClass(console);

    // Act
    productionClass.findOccuranceMethod();

    // Assert
    Assert.AreEqual(3, console.Contents.Count);
    Assert.AreEqual("String: The Haunting of Hill House!", console.Contents[0]);
    Assert.AreEqual(
        $"String after replacing a character: {expectedString}", 
        console.Contents[1]);
    Assert.AreEqual(
        $"Number of replaces made: {expectedCount}", 
        console.Contents[2]);
}

答案 1 :(得分:1)

如果您需要保留签名,可以使用可选参数:

    public void optionSameSignature(Action<string> log = null, Func<string> read = null)
    {
        log = log ?? Console.WriteLine;
        read = read ?? Console.ReadLine;

        string str = "The Haunting of Hill House!";
        log("String: " + str);
        string occurString = "o";
        string replaceString = "MDDS";

        var array = str.Split(new[] { occurString }, StringSplitOptions.None);
        var count = array.Length - 1;
        string result = string.Join(replaceString, array);

        log("String after replacing a character: " + result);
        log("Number of replaces made: " + count);
        read();
    }

    public void Test()
    {
        List<string> lines = new List<string>();
        optionSameSignature(lines.Add, () => "");
    }

从更深层次上讲,输入和输出是技术细节,因此理想情况下,您将尝试使用没有技术细节的业务价值代码。这样的事情可能更接近您的实际需求:

    private static void mybusinessfunction(string input, out int count, out string result)
    {
        string occurString = "o";
        string replaceString = "MDDS";

        var array = input.Split(new[] { occurString }, StringSplitOptions.None);
        count = array.Length - 1;
        result = string.Join(replaceString, array);
    }