如何为异常编写MS单元测试 当异常引发时,将自定义消息写入控制台



我写了一个将人员列表写入文本文件的方法,在单元测试中,我想检查我是否为列表传递了 NULL,NullReferenceException 正在抛出。

方法

public void WriteToOutput(List<Person> list)
        {
            string outputFileName = "names-list.txt";
            try
            {
                StreamWriter sw = new StreamWriter(outputFileName, false);
                foreach (var item in list)
                {
                    sw.WriteLine(item.givenNames + " " + item.lastName);
                    Console.WriteLine(item.givenNames + " " + item.lastName);//writting names to console
                }
                Console.WriteLine("Press Enter to Exit...");
                sw.Close();
            }
            catch (NullReferenceException ex)
            {
                Console.WriteLine("List is Empty");
                throw new NullReferenceException();
            }
        }

测试方法

[TestMethod]
        public void WriteToOutput_NullableList_ThrowNullReferenceException()
        {
            //arrange
            FileWriter fw = new FileWriter();
            //act
            Assert.ThrowsException<NullReferenceException>(()=> fw.WriteToOutput(null));
        }

但我不想在 WriteToOutput 方法中抛出 NullReferenceException,而只想将消息写入控制台。 如果我从方法"写入输出"中删除"抛出新的 NullReferenceException",我的测试就会失败。

关于如何处理此问题的任何意见。

首先,您将删除对Console的依赖并将其更改为Action<string>

public class FileWriter
{
    public Action<string> Log { get; set; }
    public void WriteToOutput(List<Person> list)
    {
        ...
        Log("List is Empty");
    }
}

现在,您可以根据需要插入委托。

 var writer = new FileWriter();
 writer.Log = Console.WriteLine;

该类将写入控制台。

对于测试,我们提供不同的委托。

[TestMethod]
public void WriteToOutput_NullableList_ThrowNullReferenceException()
{
    var message = "";
    Action<string> testlog = (string msg) => { message = msg; };
    var writer = new FileWriter();
    writer.Log = testlog;
    Assert.AreEqual(message, "List is Empty");
}

我会使用TextWriter进行输出

public class FileWriter
{
    private readonly TextWriter _console;
    public FileWriter(TextWriter console)
    {
        _console = console;
    }
    public void WriteToOutput(List<Person> list)
    {
        string outputFileName = "names-list.txt";
        try
        {
            using (StreamWriter sw = new StreamWriter(outputFileName, false))
            {
                foreach (var item in list)
                {
                    sw.WriteLine(item.GivenNames + " " + item.LastName);
                    _console.WriteLine(item.GivenNames + " " + item.LastName); //writting names to console
                }
                _console.WriteLine("Press Enter to Exit...");
                sw.Close();
            }
        }
        catch (NullReferenceException ex)
        {
            _console.WriteLine("List is Empty");
        }
    }
}

然后在测试中

    var sb = new StringBuilder();
    var fw = new FileWriter(new StringWriter(sb));
    //act
    fw.WriteToOutput(null);
    Assert.AreEqual("List is Emptyrn", sb.ToString());

并在控制台的程序中

var peopleWriter = new FileWriter(Console.Out);

然后你也可以测试你的主案例

fw.WriteToOutput(new List<Person>()
{
   new Person() { GivenNames = "Dula", LastName = "Hula" },
   new Person() {GivenNames = "Ruby", LastName = "Nooby"}
});
Assert.AreEqual("Dula HularnRuby NoobyrnPress Enter to Exit...rn", sb.ToString());

由于您不想在人员列表为空时引发异常,因此您的测试应该与成功测试相反(当列表包含记录时)。这样,您就不依赖于控制台消息。或您可以更改方法WriteToOutput以返回布尔值,然后在测试中检查返回值,即

    public void WriteToOutput(List<Person> list)
    {
        string outputFileName = "names-list.txt";
        try
        {
            // other stuff
            return true;
        }
        catch (NullReferenceException ex)
        {
            Console.WriteLine("List is Empty");
            return false;
        }
    }
    [TestMethod]
    public void WriteToOutput_NullableList_ThrowNullReferenceException()
    {
        //arrange
        FileWriter fw = new FileWriter();
        //act
        bool returnValue = fw.WriteToOutput(null);
        //assert
        Assert.IsFalse(returnValue);
    }

最新更新