如何对返回func的字典进行单元测试?

时间:2013-01-21 07:15:36

标签: c# rhino-mocks

我的代码如下所示:

public class FileFormatLookup : Dictionary<string,Func<string>>
{
    private Workbook workbook;
    private MemoryStream memoryStream;

    public  FileFormatLookup(Workbook workbook, MemoryStream memoryStream)
    {
        this.workbook = workbook;
        this.memoryStream = memoryStream;
        Add();
    }

    private void Add()
    {
        base.Add("xls", () =>
                            {
                                workbook.Save(memoryStream, SaveFormat.Excel97To2003);
                                return "ms-excel";
                            });
    }
}

我正在尝试编写如下测试:

class FileFormatLookupTest
{
    FileFormatLookup fileFormatLookup;
    private Workbook workbook;
    private MemoryStream memoryStream;

    [SetUp]
    public void SetUp()
    {
        fileFormatLookup = new FileFormatLookup(workbook, memoryStream);
        workbook = MockRepository.GenerateMock<Workbook>();
        memoryStream = MockRepository.GenerateMock<MemoryStream>();
    }

    [TearDown]
    public void TearDown()
    {
      workbook.VerifyAllExpectations();
    }


    [Test]
    public void ShouldHaveXlsKey()
    {
        var xlsResult = fileFormatLookup["xls"].Invoke();
        workbook.AssertWasCalled(x=>x.Save(memoryStream,SaveFormat.Excel97To2003));
     }
}

这是在字典中测试仿函数的正确方法吗? 它抛出了这个错误:

System.InvalidOperationException : No expectations were setup to be verified, ensure that the method call in the action is a virtual (C#) / overridable (VB.Net) method call

如何测试返回函数的字典?可能吗? 我可以断言返回的字符串值,但不能断言方法调用。

1 个答案:

答案 0 :(得分:2)

你没有将你的模拟传递给正在测试的课程。

将设置更改为

[SetUp]
public void SetUp()
{
    workbook = MockRepository.GenerateMock<Workbook>();
    memoryStream = MockRepository.GenerateMock<MemoryStream>();
    fileFormatLookup = new FileFormatLookup(workbook, memoryStream);
}

从错误消息中,它看起来需要设置期望,即调用您期望的模拟对象。在这种情况下workbook.Save(...)

为此,workbook.Save(...)必须是虚拟的或在接口上。


编辑:在作为评论提供的进一步信息之后。

如果workbook.Save(...)不是虚拟的而不在您的代码中,则必须使用稍长的路径才能测试该对象。

创建自己的IWorkbook接口,实现Save()方法,然后创建WorkbookWrapper类,其中包含第三方Workbook类的实例并实现IWorkbook通过将调用转发给包装类。

public interface IWorkbook
{
    void Save(...);
}

class WorkbookWrapper : IWorkbook
{
    private _workbook;

    public WorkbookWrapper(...)
    {
        _workbook = new Workbook(...);
    }

    public void Save(...)
    {
        _workbook.Save(...);
    }
}

然后更改代码以取代IWorkbook

private Workbook _workbook;

public FileFormatLookup(IWorkbook workbook, MemoryStream memoryStream)
{
    _workbook = workbook;
    _memoryStream = memoryStream;
    Add();
}

然后,您可以对其他类使用相同的技术,例如MemoryStream