我有一个使用StreamReader的方法,我想对它进行单元测试。我已经将StreamReader的创建分割成一个单独的类,并试图模拟这个类,但是我的单元测试仍然给我带来了错误。
用于抽象StreamReader的类/接口
public interface IPathReader
{
TextReader CreateReader(string path);
}
public class PathReader : IPathReader
{
public TextReader CreateReader(string filePath)
{
return new StreamReader(filePath);
}
}包含GetLastRowInFile的类(尝试单元测试的方法im )。
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
[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为您的时间。
编辑
测试方法:
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;
}
}编辑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);
}发布于 2012-08-09 09:13:28
还不清楚你为什么要在这里使用嘲弄。
是的,使用TextReader而不是要求StreamReader将为您提供更多的灵活性。很少有这样的情况,即它显式地将StreamReader指定为参数或返回类型。
如果要为StreamReader提供测试数据,只需创建包装MemoryStream的StreamReader
当您返回一个StringReader时,当它被强制转换(或者在模拟框架本身中)时,这确实会导致异常。不幸的是,您的异常处理过于宽泛,因此很难看出这个问题。您的catch块可能只捕获IOException --如果真的有什么的话。(如果无法读取资源,您真的想返回-1吗?为什么不让例外的泡沫浮出水面呢?)捕获Exception应该是非常罕见的--基本上只有在大型操作(例如web服务请求)的顶层才能捕获,以避免在进程继续执行其他操作时杀死它。
https://stackoverflow.com/questions/11880108
复制相似问题