ユニットテストしたい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にはデフォルトのコンストラクターが含まれていないため、直接モックできるとは思わないため、GetLastRowInFileからStreamReaderを作成する必要があります。
質問
- CreateReaderの戻りタイプはTextReaderである必要がありますか?
- rowReaderに割り当てる前に、返されたTextReaderをStringReaderに明示的にキャストする必要がありますか?
- IPathReaderインターフェイスのモックを作成し、代わりにStringReaderを返すようにCreateReaderを設定すると、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はこれについていくつかの助けに本当に感謝しています。お時間をいただきありがとうございます。
編集
試験方法:
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クラスの最後から3番目のメソッドに適用されます)
[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);
}