Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving multiple Moq objects based on a condition using Autofac

Hi I am using Moq with Autofac while creating unit tests. I have scenario where my SUT mutiple instances of a type depending on the constructor parameter. i would like to Moq these instances. I have an interface ISpanRecord:

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

I have another interface IRecordTypeFactory which provides for a new ISpanRecord on the basis of RecordType (which is an enum)

interface IRecordTypeFactory
{
ISpanRecord GetNewSpanRecord(RecordType recordType);
}

The above interface is used by the SUT SpanParser class

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;
        } 
    }

In the above class, while testing, i would like to get multiple objects of ISpanRecord on the basis of RecordType. Something like:

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

As the above setup would be verified in a loop, so i would like to setup multiple cases. Please let me know what can be the solution or point me to the threads which do.

Regards

like image 852
Darsin Avatar asked Jun 15 '26 13:06

Darsin


1 Answers

Returns has multiple overloads, you're looking for those that take Func<RecordType, ISpanRecord> as argument. Having that sorted, you can build your custom return-logic:

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();
    }); 

Is there any reason you're using service locator instead of abstract factory? If your container wasn't embedded in your SUT, perhaps tests would be easier (say, you wouldn't have to keep track of container itself and dependencies registering process).

like image 177
k.m Avatar answered Jun 19 '26 17:06

k.m



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!