0

我正在尝试编写一个单元测试来写入它使用 File.OpenWrite() 打开的文件。

我正在使用 SystemWrapper 的 IFileWrap 接口包装文件。在生产中,我使用 SimpleInjector 来注入 SystemWrapper 的 FileWrap 类的实例,并且工作正常。但是我试图在我的单元测试中使用 MOQ 来模拟 IFileWrap,但这是行不通的。

我是 SystemWrapper 的新手,我正在尽我所能弄清楚它的用途。据我所知,IFileWrap.OpenWrite() 返回一个 IFileWrap 实例,您可以从中获取带有 FileStreamInstance 的流。

因此,在我的测试类中,我在构造函数中注入了一个 IFileWrap:

public class ClassUnderTest
{
    private readonly IFileWrap fileWrap;

    public ClassUnderTest(IFileWrap fileWrap)
    {
        this.fileWrap = fileWrap;
    }

    ...
}

在我的测试方法中,我从 FileStreamInstance 获取流:

var fsWrap = this.fileWrap.OpenWrite(fullPath);
var ostream = fswrap.FileStreamInstance;

这在生产中工作得很好,其中 fileWrap 是用 FileWrap 的实例实例化的。但在我的测试中,我试图为 File.OpenWrite 创建一个 Mock,它返回一个模拟的 FileStream:

var fileStreamMock = new Mock<IFileStreamWrap>();

var fileMock = new Mock<IFileWrap>();
fileMock.Setup(fm => fm.OpenWrite(It.IsAny<string>())).Returns(fileStreamMock.Object);

var classUnderTest = new ClassUnderTest(fileMock.Object);

当我在调试器中从我的单元测试中遍历被测方法时,fsWrap.FileStreamInstance 为空,而我希望它是我的模拟文件流。

关于我做错了什么的任何想法?

4

2 回答 2

1

您不会存根FileStreamInstance返回任何内容,因此 Moq 将返回 null。

FileStreamInstance创建IFileStreamWrap模拟后,您需要设置为返回一些东西:

var fileStreamWrapMock = new Mock<IFileStreamWrap>(); // Was fileStreamMock
var fileStreamMock = new Mock<FileStream>();
fileStreamWrapMock.Setup(fswm => fswm.FileStreamInstance).Returns(fileStreamMock);
于 2015-03-19T16:17:16.717 回答
1

我最近一直在为此苦苦挣扎。正如您在评论Chris Mantle 的答案中所建议的那样,我最初通过使用临时文件解决了它。我最近偶然发现了另一种方式,使用StreamInstance而不是FileStreamInstance(不确定当您提出问题时这是否可用):

var outBuffer = new byte[512];
var fileWrap = new Mock<IFileWrap>();
var fileStreamWrap = new Mock<IFileStreamWrap>();
var stream = new Mock<IFileStreamWrap>();
fileStreamWrap.Setup(fsw => fsw.StreamInstance).Returns(new MemoryStream(outBuffer));

//I'm using File.Create to create temporary files with DeleteOnClose flag in the application, which get disposed before the function returns
fileWrap.Setup(fw => fw.Create(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<FileOptions>()))
    .Returns((string filepath, int i, FileOptions fo) =>
    {
        //I'm using filepath in a collection in my test to handle multiple files created in the application code
        return fileStreamWrap.Object;
    });


//Call application code that creates temporary file and closes eagerly with dispose.
//Application code will be something like:
var tempFileStream = _fileWrap.Create(tempFileName, 4096, FileOptions.DeleteOnClose);
using (var writer = new StreamWriter(tempFileStream.StreamInstance, Encoding.Default, 4096, true))
{...}


//Test file contents were written correctly into outBuffer
var outString = System.Text.Encoding.UTF8.GetString(outBuffer);
Assert.AreEqual("Important Business string", outString);
于 2018-07-27T07:03:44.020 回答