我有一个使用的StreamReader的方法,其我想单元测试。我把StreamReader的创建分成了一个单独的类,并试图嘲笑这个类,但是我的单元测试仍然给我错误。惩戒一个StreamReader
类/接口用于抽象含有GetLastRowInFile(方法即时试图单元测试)的StreamReader的
public interface IPathReader
{
TextReader CreateReader(string path);
}
public class PathReader : IPathReader
{
public TextReader CreateReader(string filePath)
{
return new StreamReader(filePath);
}
}
类。
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的。
问题
- 应该CreateReader的返回类型为TextReader的?
- 我是否需要将其分配给rowReader之前明确转换返回的TextReader回StringReader?
- 当我创建IPathReader接口的模拟效果和设立CreateReader返回一个StringReader替换,当它被分配到rowReader会发生什么。我认为不可能在相同的继承层次上施放某些东西?
单元测试如下:它不断地返回-1
[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);
}
林假设有最根本的是我在想念所以ID真的很感激一些帮助this.Thanks您时间。
编辑
测试方法:
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);
}
存根声明:
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;
}
}
EDIT 2
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类)
[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);
}
我是StreamReader的实际访问指定文件的印象,并且因此,我需要模拟它。从你说过的话,即时通讯假设我错了?捕捉异常的想法是因为我想让程序通过所有的检查。然后它检查errorMessage中是否包含任何内容。如果是这样,它不会让用户继续进行并通知他们错误。我认为这将是最好的一次,而不是1个错误让所有的错误,纠正它,重新运行,下一个错误,正确的是等(这可能是一个有缺陷的方法吗?) – 2012-08-09 09:50:18
@HansRudel:不,它读取*流*。任何流。碰巧有一些便利的构造函数可以为你创建一个'FileStream',但也有其他的可以使用任何流。 – 2012-08-09 10:02:12
这是正确的吗? (请参阅编辑原始问题的底部。)你如何确定你是否需要嘲笑一些东西。即StreamReader等? – 2012-08-09 11:23:29