使用Autofac根据条件解析多个Moq对象

时间:2013-01-14 15:31:55

标签: unit-testing c#-3.0 moq autofac

您好我在创建单元测试时使用Moq和Autofac。我有一个场景,我的SUT多个类型的实例取决于构造函数参数。我想Moq这些实例。 我有一个界面 ISpanRecord

interface ISpanRecord 
{
RecordType RecordType { get; }
string RecordId { get; set; }
string RecordText { get; set; }
ISpanRecord ParentRecord { get; set; }
List<ISpanRecord> Children { get; }
}

我有另一个界面 IRecordTypeFactory ,它基于 RecordType (这是一个枚举)提供了一个新的 ISpanRecord

interface IRecordTypeFactory
{
ISpanRecord GetNewSpanRecord(RecordType recordType);
}

上述界面由SUT SpanParser

使用
internal class SpanParser : ISpanParser
{
// Private Vars
    private ISpanRecord _spanFile;
    private readonly IRecordTypeFactory _factory;
    private readonly ISpanFileReader _fileReader;

//Constructor
public SpanParser(ISpanFileReader fileReader)
    {
        _fileReader = fileReader;
        _spanFile = Container.Resolve<ISpanRecord>(TypedParameter.From(RecordType.CmeSpanFile),
                                                                TypedParameter.From((List<SpanRecordAttribute>)null));
        _factory = Container.Resolve<IRecordTypeFactory>(TypedParameter.From(_fileReader.PublisherConfiguration));
    }

// Method under test
public SpanRiskDataSetEntity ParseFile()
    {
        string currRecord = string.Empty;
        try
        {
            var treeLookUp = Container.Resolve<ITreeLookUp>(TypedParameter.From(_spanFile),
                                                            TypedParameter.From(_fileReader.PublisherConfiguration));

            IList<string> filterLines = _fileReader.SpanFileLines;

            ISpanRecord currentRecord;
            ISpanRecord previousRecord = _spanFile;
            List<string> spanRecords;

            foreach (var newRecord in filterLines)
            {
                currRecord = newRecord;

                //check if we got multiple type of records in a single line.

                spanRecords = _fileReader.PublisherConfiguration.GetMultipleRecordsText(newRecord);
                if (spanRecords == null)
                    continue;

                foreach (var recordText in spanRecords)
                {
                    RecordType recordType = _fileReader.PublisherConfiguration.GetRecordType(recordText);

                    currentRecord = _factory.GetNewSpanRecord(recordType);

                    // some more logic

                    GetPreviousRecord(ref previousRecord, currentRecord);
                }
            }
            // private method
            return GetSpanRiskDataSet();
        }

        catch (OperationCanceledException operationCanceledException)
        {
            // log
            throw;
        } 
    }

在上面的课程中,在测试时,我希望在RecordType的基础上获得 ISpanRecord 的多个对象。 类似的东西:

mockFactory.Setup(fc=> fc.GetNewSpanRecord(It.IsAny<RecordType>).Returns(// an ISpanRecord object on the basis of Recordtype)

由于上面的设置将在循环中验证,所以我想设置多个案例。请让我知道什么是解决方案或指向我的线程。

此致

2 个答案:

答案 0 :(得分:3)

Returns有多个重载,你正在寻找以Func<RecordType, ISpanRecord>为参数的那些重载。排序后,您可以构建自定义返回逻辑:

mockFactory
    .Setup(fc => fc.GetNewSpanRecord(It.IsAny<RecordType>)
    .Returns((RecordType rt) =>
    {
         if (rt.Property == "value") return new DummySpanRecord();
         else if (rt.Property2 == "other value") return new FakeSpanRecord();
         else return new DefaultSpanRecord();
    }); 

你有没有理由使用service locator instead of abstract factory?如果你的容器没有嵌入你的SUT,也许测试会更容易(比如说,你不必跟踪容器本身和依赖注册过程)。

答案 1 :(得分:2)

在您的设置中,请勿使用It.IsAny<RecordType> - 使用特定值:

mockFactory.Setup(fc=> fc.GetNewSpanRecord(RecordType.Type1)).Returns(// an ISpanRecord object on the basis of Recordtype.Type1)
mockFactory.Setup(fc=> fc.GetNewSpanRecord(RecordType.Type2)).Returns(// an ISpanRecord object on the basis of Recordtype.Type2)

编辑:这假设RecordType是枚举(或其他值类型)的简单情况。如果它是引用类型,则需要使用更复杂的技术,如jimmy's。