首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >嘲弄StreamReader

嘲弄StreamReader
EN

Stack Overflow用户
提问于 2012-08-09 09:11:04
回答 1查看 11.5K关注 0票数 3

我有一个使用StreamReader的方法,我想对它进行单元测试。我已经将StreamReader的创建分割成一个单独的类,并试图模拟这个类,但是我的单元测试仍然给我带来了错误。

用于抽象StreamReader的类/接口

代码语言:javascript
复制
public interface IPathReader
{
    TextReader CreateReader(string path);
}

public class PathReader : IPathReader
{
    public TextReader CreateReader(string filePath)
    {
        return new StreamReader(filePath);
    }
}

包含GetLastRowInFile的类(尝试单元测试的方法im )。

代码语言:javascript
复制
public interface IIOManager
{
    int GetLastRowInFile(string filePath, List<String> errorMessageList);
}


public class IOManager : IIOManager
{
    private IPathReader _reader;

    public IOManager(IPathReader reader)
    {
        this._reader = reader;
    }

    //...

    public int GetLastRowInFile(string filePath, List<String> errorMessage)
    {
        int numberOfRows = 0;
        string dataRow;

        try
        {
            using (StreamReader rowReader = (StreamReader)_reader.CreateReader(filePath))
            {
                while ((rowReader.Peek()) > -1)
                {
                    dataRow = rowReader.ReadLine();
                    numberOfRows++;
                }
                return numberOfRows;
            }
        }
        catch (Exception ex)
        {
            errorMessage.Add(ex.Message);
            return -1;
        }
    }
}

StreamReader不包含默认构造函数,因此我不相信我可以直接模拟它,因此需要将StreamReader的创建从GetLastRowInFile中删除。

问题

  1. 返回类型的CreateReader是否应该是TextReader?
  2. 在将返回的TextReader分配给rowReader之前,是否需要显式地将返回的rowReader转换回rowReader?
  3. 当我创建一个IPathReader接口的模拟并设置CreateReader来返回一个StringReader时,当它被分配给rowReader时会发生什么。我认为不可能在相同的继承级别上抛出某种东西?

继承层次

单元测试如下所示,并不断返回-1

代码语言:javascript
复制
    [Test]
    public void GetLastRowInFile_ReturnsNumberOfRows_Returns3()
    {
        string testString = "first Row" + Environment.NewLine + "second Line" + Environment.NewLine + "Third line";
        List<String> errorMessageList = new List<string>();

        Mock<IPathReader> mock = new Mock<IPathReader>();
        mock.Setup(x => x.CreateReader(It.IsAny<string>())).Returns(new StringReader(testString));

        IOManager testObject = new IOManager(mock.Object);

        int i = testObject.GetLastRowInFile(testString, errorMessageList);              //Replace with It.IsAny<string>()
        Assert.AreEqual(i, 3);
        Assert.AreEqual(errorMessageList.Count, 0);
    }

我假设有基本的,我错过了,所以我真的很感谢一些帮助与this.Thanks为您的时间。

编辑

测试方法:

代码语言:javascript
复制
    public void GetLastRowInFile_ReturnsNumberOfRows_Returns3()
    {
        StubGetLastRowInFile myStub = new StubGetLastRowInFile();
        List<String> errorMessageList = new List<string>();
        IOManager testObject = new IOManager(myStub);
        int i = testObject.GetLastRowInFile(It.IsAny<string>(), errorMessageList);
        Assert.AreEqual(i, 3);
        Assert.AreEqual(errorMessageList.Count, 0);
    }

存根声明:

代码语言:javascript
复制
public class StubGetLastRowInFile : IPathReader
{
    public TextReader CreateReader(string path)
    {
        //string testString = "first Row" + Environment.NewLine + "second Line" + Environment.NewLine + "Third line";
        string testString = "04/01/2010 00:00,1.4314,1.4316";
        UTF8Encoding encoding = new UTF8Encoding();
        UnicodeEncoding uniEncoding = new UnicodeEncoding();

        byte[] testArray = encoding.GetBytes(testString);

        MemoryStream ms = new MemoryStream(testArray);

        StreamReader sr = new StreamReader(ms);

        return sr;
    }
}

编辑2

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Data;
using System.Globalization;
using System.Collections;
using System.Reflection;
using System.ComponentModel;

namespace FrazerMann.CsvImporter.Entity
{
    public interface IPathReader
    {
        TextReader CreateReader(string path);
    }

    public class PathReader : IPathReader
    {
        public TextReader CreateReader(string filePath)
        {
            return new StreamReader(filePath);
        }
    }


public interface IIOManager
{
    Stream OpenFile(string path);

    int GetLastRowInFile(string filePath, List<String> errorMessageList);

    int GetNumberOfColumnsInFile(string filePath, List<string> errorMessageList);

    bool IsReadOnly(string filePath);
}


public class IOManager : IIOManager
{
    private IPathReader _reader;

    public IOManager(IPathReader reader)
    {
        this._reader = reader;
    }


    public Stream OpenFile(string path)
    {
        return new FileStream(path, FileMode.Open);
    }


    public int GetNumberOfColumnsInFile(string filePath, List<String> errorMessageList)
    {
        int numberOfColumns = 0;
        string lineElements;

        try
        {
            using (StreamReader columnReader = (StreamReader)_reader.CreateReader(filePath))
            {
                lineElements = columnReader.ReadLine();
                string[] columns = lineElements.Split(',');
                numberOfColumns = columns.Length;
            }
        }
        catch (Exception ex)
        {
            errorMessageList.Add(ex.Message);
            numberOfColumns = -1;
        }
        return numberOfColumns;
    }


    public int GetLastRowInFile(string filePath, List<String> errorMessage)
    {
        int numberOfRows = 0;
        string dataRow;

        try
        {
            using (StreamReader rowReader = (StreamReader)_reader.CreateReader(filePath))
            {
                while ((rowReader.Peek()) > -1)
                {
                    dataRow = rowReader.ReadLine();
                    numberOfRows++;
                }
                return numberOfRows;
            }
        }
        catch (Exception ex)
        {
            errorMessage.Add(ex.Message);
            return -1;
        }
    }


    public bool IsReadOnly(string filePath)
    {
        FileInfo fi = new FileInfo(filePath);
        return fi.IsReadOnly;
    }
}


public interface IVerificationManager
{
    void ValidateCorrectExtension(string filePath, List<String> errorMessageList);

    void ValidateAccessToFile(string filePath, List<String> errorMessageList);

    void ValidateNumberOfColumns(string filePath, int dataTypeCount, List<String> errorMessageList);

    int ValidateFinalRow(int finalRow, string filePath, List<String> errorMessageList);

    void ValidateRowInputOrder(int initialRow, int finalRow, List<String> errorMessageList);

    void EnumeratedDataTypes(UserInputEntity inputs, List<String> errorMessageList);

    int GetProgressBarIntervalsForDataVerification(int initialRow, int finalRow, List<String> errorMessageList);
}


public class VerificationManager : IVerificationManager
{
    private IIOManager _iomgr;

    public VerificationManager(IIOManager ioManager)
    {
        this._iomgr = ioManager;
    }

    public void ValidateCorrectExtension(string filePath, List<String> errorMessageList)
    {
        if (filePath.EndsWith(".txt", StringComparison.OrdinalIgnoreCase) | filePath.EndsWith(".csv", StringComparison.OrdinalIgnoreCase)) { }
        else
        {
            errorMessageList.Add("Selected file does not have a compatable extension.");
        }
    }

    public void ValidateAccessToFile(string filePath, List<String> errorMessageList)
    {
        try
        {

            if (_iomgr.IsReadOnly(filePath) == true) { }
            else
            {
                errorMessageList.Add("Can not read/write to the specified file.");
            }
        }
        catch (Exception e)
        {
            errorMessageList.Add(e.Message);
        }
    }

    public void ValidateNumberOfColumns(string filePath, int userSpecifiedColumnCount, List<String> errorMessageList)
    {
        int numberOfColumnsInFile = _iomgr.GetNumberOfColumnsInFile(filePath, errorMessageList);

        if (userSpecifiedColumnCount != numberOfColumnsInFile) errorMessageList.Add("Number of columns specified does not match number present in file.");
    }

//**TEST APPLIES HERE**

    public int ValidateFinalRow(int finalRow, string filePath, List<String> errorMessageList)
    {
        int totalNumberOfRowsInFile = 0;

        totalNumberOfRowsInFile = _iomgr.GetLastRowInFile(filePath, errorMessageList);

        if (totalNumberOfRowsInFile != -1)
        {
            if (finalRow == 0)
            {
                return totalNumberOfRowsInFile;
            }
            else
            {
                if (finalRow > totalNumberOfRowsInFile)
                {
                    errorMessageList.Add("Specified 'Final Row' value is greater than the total number of rows in the file.");
                }
            }
        }
        return 0;
    }

    public void ValidateRowInputOrder(int initialRow, int finalRow, List<String> errorMessageList)
    {
        if (initialRow > finalRow)
        {
            errorMessageList.Add("Initial row is greater than the final row.");
        }
    }

    public void EnumeratedDataTypes(UserInputEntity inputs, List<String> errorMessageList)
    {
        inputs.EnumeratedDataTypes = new int[inputs.DataTypes.Count];
        try
        {
            for (int i = 0; i < inputs.DataTypes.Count; i++)
            {
                inputs.EnumeratedDataTypes[i] = (int)Enum.Parse(typeof(Enumerations.ColumnDataTypes), inputs.DataTypes[i].ToUpper());
            }
        }
        catch (Exception ex)
        {
            errorMessageList.Add(ex.Message);
        }
    }

    public int GetProgressBarIntervalsForDataVerification(int initialRow, int finalRow, List<String> errorMessageList)
    {
        int progressBarUpdateInverval = -1;

        try
        {
            int dif = (finalRow - initialRow) + 1;
            progressBarUpdateInverval = dif / 100;

            if (progressBarUpdateInverval == 0)
            {
                progressBarUpdateInverval = 1;
            }
        }
        catch (Exception ex)
        {
            errorMessageList.Add(ex.Message);
        }
        return progressBarUpdateInverval;
    }
}



public class EntityVerification
{

    private VerificationManager _vmgr;

    public EntityVerification(VerificationManager vManager)
    {
        this._vmgr = vManager;
    }


    public void VerifyUserInputManager(UserInputEntity inputs, List<string> errorMessageList)
    {
        _vmgr.ValidateCorrectExtension(inputs.CsvFilePath ,errorMessageList);
        _vmgr.ValidateCorrectExtension(inputs.ErrorLogFilePath, errorMessageList);

        _vmgr.ValidateAccessToFile(inputs.CsvFilePath, errorMessageList);
        _vmgr.ValidateAccessToFile(inputs.ErrorLogFilePath, errorMessageList);

        _vmgr.ValidateNumberOfColumns(inputs.CsvFilePath, inputs.DataTypes.Count, errorMessageList);

        inputs.FinalRow = _vmgr.ValidateFinalRow(inputs.FinalRow, inputs.CsvFilePath, errorMessageList);

        _vmgr.ValidateRowInputOrder(inputs.InitialRow, inputs.FinalRow, errorMessageList);

        _vmgr.EnumeratedDataTypes(inputs, errorMessageList);

        inputs.ProgressBarUpdateIntervalForDataVerification = _vmgr.GetProgressBarIntervalsForDataVerification(inputs.InitialRow, inputs.FinalRow, errorMessageList);
    }
}
}

测试方法(适用于VerificationManager类中的最后一个方法)

代码语言:javascript
复制
    [Test]
    public void ValidateFinalRow_FinalRowReturned_Returns6()
    {
        List<String> errorMessageList = new List<string>();                             //Remove if replaced

        Mock<IIOManager> mock = new Mock<IIOManager>();
        mock.Setup(x => x.GetLastRowInFile(It.IsAny<String>(), errorMessageList)).Returns(6);

        VerificationManager testObject = new VerificationManager(mock.Object);
        int i = testObject.ValidateFinalRow(0, "Random", errorMessageList);             //Replace with It.IsAny<string>()  and It.IsAny<List<string>>()
        Assert.AreEqual(i, 6);
    }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-08-09 09:13:28

还不清楚你为什么要在这里使用嘲弄。

是的,使用TextReader而不是要求StreamReader将为您提供更多的灵活性。很少有这样的情况,即它显式地将StreamReader指定为参数或返回类型。

如果要为StreamReader提供测试数据,只需创建包装MemoryStreamStreamReader

当您返回一个StringReader时,当它被强制转换(或者在模拟框架本身中)时,这确实会导致异常。不幸的是,您的异常处理过于宽泛,因此很难看出这个问题。您的catch块可能只捕获IOException --如果真的有什么的话。(如果无法读取资源,您真的想返回-1吗?为什么不让例外的泡沫浮出水面呢?)捕获Exception应该是非常罕见的--基本上只有在大型操作(例如web服务请求)的顶层才能捕获,以避免在进程继续执行其他操作时杀死它。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11880108

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档