如何在异常抛出时编写MS Unit test for Exception,将自定义消息写入控制台

时间:2017-11-02 01:22:37

标签: c# unit-testing try-catch nullreferenceexception assert

我编写了一个方法,将一个人列表写入文本文件,在单元测试中,我想检查是否为列表传递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,而只是将消息写入控制台。如果我删除&#39;抛出新的NullReferenceException&#39;来自方法&#39; WriteToOutput&#39;我的考试很不错。

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

3 个答案:

答案 0 :(得分:1)

首先,您删除对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;

该课程将写入Console。

对于测试,我们提供了不同的代表。

[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");
}

答案 1 :(得分:1)

我会使用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 Empty\r\n", 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 Hula\r\nRuby Nooby\r\nPress Enter to Exit...\r\n", sb.ToString());

答案 2 :(得分:0)

由于如果人员列表为空,您不想抛出异常,那么您的测试应该与您的成功测试相反(当列表包含记录时)。这样您就不依赖于控制台消息。 要么 你可以改变你的方法WriteToOutput返回bool然后在测试你检查返回值,即

    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);
    }