1

我最近开始使用 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;
            }
        }
    }

这段代码需要物理文件来检查它是否工作正常,但是单元测试是否依赖于物理文件?
如何为这样的代码编写单元测试?

4

3 回答 3

3

单元测试不应依赖外部资源,如文件系统或数据库等。在这种情况下,您必须使用MoqRhino Mock等模拟框架。如果您想测试您的代码及其外部依赖项,您应该编写Integration Test.

所以在你的情况下,如果你不想使用任何模拟框架,你可以为依赖创建自己的假类,并通过依赖注入模式传递它们

于 2013-02-03T13:28:17.900 回答
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上发布生产代码和测试以获得一些反馈。

于 2013-02-03T14:30:14.153 回答
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)));
于 2013-02-05T03:48:29.533 回答