我最近开始使用NUnit框架为我的代码编写单元测试。
我熟悉NUnit的基本概念并编写简单的测试。
实际上我不知道如何测试使用文件的代码:
例如,我想为下面的类编写测试:
public class ShapeLoader
{
private static void StreamLoading(object sender, StreamLoadingEventArgs e)
{
try
{
string fileName = Path.GetFileName(e.AlternateStreamName);
string directory = Path.GetDirectoryName(e.AlternateStreamName);
e.AlternateStream = File.Exists(directory + @"\\" + fileName) ? new FileStream(directory + @"\\" + fileName, e.FileMode, e.FileAccess) : null;
}
catch
{ }
}
public static ShapeFileFeatureLayer Load(string filePath, ShapeFileReadWriteMode shapeFileReadWriteMode, bool buildIndex = true)
{
if (!File.Exists(filePath)) { throw new FileNotFoundException(); }
try
{
switch (shapeFileReadWriteMode)
{
case ShapeFileReadWriteMode.ReadOnly:
// if (buildIndex && !HasIdColumn(filePath)) BuildRecordIdColumn(filePath, BuildRecordIdMode.Rebuild);
ShapeFileFeatureLayer.BuildIndexFile(filePath, BuildIndexMode.DoNotRebuild);
var shapeFileLayer = new ShapeFileFeatureLayer(filePath, shapeFileReadWriteMode) { RequireIndex = true };
((ShapeFileFeatureSource)shapeFileLayer.FeatureSource).StreamLoading += StreamLoading;
return shapeFileLayer;
case ShapeFileReadWriteMode.ReadWrite:
return new ShapeFileFeatureLayer(filePath, shapeFileReadWriteMode);
default:
return null;
}
}
catch (Exception ex)
{
if (ex.Message.Contains("Could not find file")) throw new FileNotFoundException();
throw;
}
}
}
此代码需要物理文件来检查它是否正常工作,但单元测试与物理文件的依赖关系是否正确?
如何为这样的代码编写单元测试?
答案 0 :(得分:3)
单元测试不应与外部资源(如文件系统或数据库等)有任何依赖关系。
在这种情况下,您必须使用模拟框架,例如 Moq 或 Rhino Mock 。
如果要测试代码及其外部依赖项,则应编写Integration Test
。
所以在你的情况下,如果你不想使用任何模拟框架,你可以为依赖项创建自己的假类并通过依赖注入模式
传递它们答案 1 :(得分:1)
我喜欢创造这个:
public abstract class FileSystem
{
public abstract bool FileExists(string fullPath);
public abstract Stream OpenFile(string fullPath, FileMode mode, FileAccess access);
}
然后,您可以以明显的方式为生产代码实现它,并轻松地为测试代码进行模拟。
[Test]
public void StreamReadingEventAddsStreamToEventArgsWhenFileExists()
{
var e new StreamReadingEventArgs { e.AlternateStreamName= "Random string in path format", e.FileMode = AnyFileMode(), e.FileAccess = AnyFileAccess() };
var expectedStream = new MemoryStream();
_fileSystemMock.Setup(f=>f.OpenFile(e.AlternateStreamName, e.FileMode, e.FileAccess)).Returns(expectedStream);
SomehowFireTheEvent(e);
Assert.That(e.AlternateStream, Is.SameAs(expectedStream));
}
作为旁注,此代码还有其他可测试性问题会让您感到沮丧。我建议尝试为它编写一些测试,然后在codereview.stackexchange.com上发布生产代码和测试以获得一些反馈。
答案 2 :(得分:1)
无论您使用何种依赖项或使用外部资源,都要为每个资源创建模拟,然后使用模拟框架(如MOQ)运行测试。这是一个例子。更好地创建界面并使用界面
实现模拟 var mockEmailRequest = new Mock<IEMailRequest>
mockEmailResponse.setup(x+>x.EmailResponse).Returns(.....);
mockEmailRequest.Verify(r=>r.EmailReceived(It.Is<EmailResponse>(r=>r.Subject == "Something"),It.Is<int>(i=>i > 17)));