Beispiel #1
0
        public void RunReportSomeAccess()
        {
            var nameDescList = new List <Tuple <string, string> >
            {
                new Tuple <string, string>("Name1", "Description1"),
                new Tuple <string, string>("Name2", "Description2")
            };
            SecurityTestData testData = SetupSecurityTest(nameDescList);

            var reportingInterface = new ReportingInterface();

            // Create an access rule only for entity with Name1
            new AccessRuleFactory().AddAllowReadQuery(testData.UserAccount.As <EntityModel.Subject>(), testData.EntityType.As <EntityModel.SecurableEntity>(),
                                                      TestQueries.EntitiesWithName(testData.EntityType, "Name1").ToReport());

            ReportResult reportResult;

            using (new SetUser(testData.UserAccount))
            {
                reportResult = reportingInterface.RunReport(testData.Report, null);
            }

            foreach (var nameDesc in nameDescList)
            {
                Assert.AreEqual(nameDesc.Item1 == "Name1" ? 1 : 0, reportResult.GridData.Count(gd => gd.Values[1].Value == nameDesc.Item1 && gd.Values[2].Value == nameDesc.Item2));
            }
            Assert.AreEqual(1, reportResult.GridData.Count);
        }
Beispiel #2
0
        public void TestReportWithWriteOnlyField(bool isFieldWriteOnly)
        {
            try
            {
                var field = Entity.Get <Field>("test:afString", true);
                field.IsFieldWriteOnly = isFieldWriteOnly;
                field.Save();

                IEnumerable <IEntity> reports = Entity.GetByName("AF_String");

                var          reportInterface = new ReportingInterface();
                ReportResult result          = reportInterface.RunReport(reports.First().Id, null);

                if (isFieldWriteOnly)
                {
                    Assert.IsTrue(result.GridData.All(d => string.IsNullOrEmpty(d.Values[1].Value)), "We should not have any values");
                }
                else
                {
                    Assert.IsTrue(result.GridData.Any(d => !string.IsNullOrEmpty(d.Values[1].Value)), "We should have at least 1 value");
                }
            }
            finally
            {
                CacheManager.ClearCaches();
            }
        }
        public void TestSerializationOfReportResultCacheKey( )
        {
            /////
            // Get the AA_All Fields Report since it has rollups.
            /////
            long reportId = Entity.GetIdFromUpgradeId(new Guid("da986865-1c90-4ae4-9a48-36cd4514208c"));

            var reportingInterface = new ReportingInterface( );

            ReportCompletionData reportCompletion = reportingInterface.PrepareReport(reportId, new ReportSettings( ));

            ReportResultCacheKey reportResultCacheKey = reportCompletion.ResultCacheKey;

            using (var stream = new MemoryStream( ))
            {
                ProtoBuf.Serializer.Serialize(stream, reportResultCacheKey);

                byte [] bytes = stream.ToArray( );

                using (var stream2 = new MemoryStream(bytes))
                {
                    var key2 = ProtoBuf.Serializer.Deserialize <ReportResultCacheKey>(stream2);

                    Assert.AreEqual(key2, reportResultCacheKey);
                }
            }
        }
Beispiel #4
0
        public void Test_Rollup_Report_On_EditForm()
        {
            using (new SecurityBypassContext())
            {
                var report         = CodeNameResolver.GetInstance("AA_All Fields Rollup", "Report");
                var typeId         = Factory.ScriptNameResolver.GetTypeByName("AA_Herb");
                var instance       = CodeNameResolver.GetInstance("Basil", "AA_Herb");
                var relationshipId = Factory.ScriptNameResolver.GetMemberOfType("AA_All Fields", typeId, MemberType.Relationship).MemberId;

                ReportSettings settings = new ReportSettings
                {
                    ReportRelationship = new ReportRelationshipSettings
                    {
                        EntityId       = instance.Id,
                        RelationshipId = relationshipId,
                        Direction      = ReportRelationshipSettings.ReportRelationshipDirection.Forward
                    },
                    RequireFullMetadata = true
                };

                var          reportInterface = new ReportingInterface();
                ReportResult result          = reportInterface.RunReport(report.Id, null);

                Assert.That(result, Is.Not.Null);
                Assert.That(result.GridData, Has.Count.GreaterThan(0));
                Assert.That(result.AggregateMetadata.Groups, Has.Count.EqualTo(2));
            }
        }
Beispiel #5
0
        public void Test_MaxCols_Returns_Grouped_Columns()
        {
            using (new SecurityBypassContext())
            {
                var report = Entity.GetByName <Report>("Temperature").First(r => r.InSolution != null && r.InSolution.Name == "Foster University");

                ReportSettings settings = new ReportSettings
                {
                    ColumnCount         = 3,
                    RequireFullMetadata = true
                };

                var          reportInterface = new ReportingInterface();
                ReportResult result          = reportInterface.RunReport(report.Id, settings);

                Assert.That(result, Is.Not.Null);
                Assert.That(result.GridData, Has.Count.GreaterThan(0));
                Assert.That(result.GridData[0].Values, Has.Count.EqualTo(4));
                Assert.That(result.Metadata.ReportColumns, Has.Count.EqualTo(4));
                Assert.That(result.AggregateMetadata.Groups, Has.Count.EqualTo(1));
                Assert.That(result.AggregateMetadata.Groups[0], Has.Count.EqualTo(1));
                long groupColumnId = result.AggregateMetadata.Groups[0].Keys.First();
                Assert.IsTrue(result.Metadata.ReportColumns.ContainsKey(groupColumnId.ToString(CultureInfo.InvariantCulture)));
            }
        }
Beispiel #6
0
        public void TestReportsReportFiltersReportsAssignedToAccessRules( )
        {
            using (new SecurityBypassContext( ))
            {
                var reportsReport = Entity.Get <ReadiNow.Model.Report>("k:reportsReport");

                var          reportInterface = new ReportingInterface( );
                ReportResult result          = reportInterface.RunReport(reportsReport, null);

                var errors = new StringBuilder( );

                foreach (DataRow row in from row in result.GridData let report = Entity.Get <ReadiNow.Model.Report>(row.EntityId) where report != null where report.ReportForAccessRule != null select row)
                {
                    if (errors.Length > 0)
                    {
                        errors.Append(",");
                    }
                    errors.AppendFormat("{0}", row.EntityId);
                }

                if (errors.Length > 0)
                {
                    errors.Insert(0, "The following reports are assigned to access rules: ");
                    Assert.Fail(errors.ToString( ));
                }
            }
        }
        public void Check_StructuredQuery_Invalidation_On_ReportInterface( )
        {
            using (CacheManager.EnforceCacheHitRules(false))
            {
                Report             report;
                ResourceReportNode rootNode;
                ResourceArgument   exprType;

                // Create report
                using (var ctx = DatabaseContext.GetContext(true, preventPostSaveActionsPropagating: true))
                {
                    report   = new EntityModel.Report();
                    rootNode = new ResourceReportNode();
                    var reportType = EntityModel.Entity.Get <EntityType>("test:person");;
                    rootNode.ResourceReportNodeType = reportType;
                    report.RootNode = rootNode.As <ReportNode>();
                    var column = new EntityModel.ReportColumn( );
                    exprType = new ResourceArgument();
                    exprType.ConformsToType = reportType;
                    var expr = new EntityModel.ResourceExpression();
                    expr.ReportExpressionResultType = exprType.As <ActivityArgument>();
                    expr.SourceNode         = rootNode.As <ReportNode>();
                    column.ColumnExpression = expr.As <ReportExpression>();
                    report.ReportColumns.Add(column);
                    report.Save();
                    ctx.CommitTransaction();
                }

                ReportingInterface ri = new ReportingInterface( );
                var settings          = new ReportSettings
                {
                    InitialRow           = 0,
                    PageSize             = 1,
                    RequireFullMetadata  = true,
                    RequireBasicMetadata = true
                };

                // Run and expect 1 column
                var result = ri.RunReport(report.Id, settings);
                Assert.AreEqual(1, result.ReportQueryColumns.Count);

                // Add column
                using (var ctx = DatabaseContext.GetContext(true, preventPostSaveActionsPropagating: true))
                {
                    var column2 = new EntityModel.ReportColumn();
                    var expr2   = new EntityModel.ResourceExpression();
                    expr2.SourceNode = rootNode.As <ReportNode>();
                    expr2.ReportExpressionResultType = exprType.As <ActivityArgument>();
                    column2.ColumnExpression         = expr2.As <ReportExpression>();
                    report.ReportColumns.Add(column2);
                    report.Save();
                    ctx.CommitTransaction();
                }

                // Run and expect 2 columns
                result = ri.RunReport(report.Id, settings);
                Assert.AreEqual(2, result.ReportQueryColumns.Count);
            }
        }
Beispiel #8
0
        public void TestReport_AF_String( )
        {
            long reportId = Entity.GetByName("AF_String").First( ).Id;

            var          reportInterface = new ReportingInterface( );
            ReportResult result          = reportInterface.RunReport(reportId, null);

            Assert.That(result, Is.Not.Null);
            Assert.That(result.GridData, Has.Count.GreaterThan(0));
        }
Beispiel #9
0
        public void RunReportNoAccess()
        {
            SecurityTestData testData = SetupSecurityTest(new List <Tuple <string, string> >
            {
                new Tuple <string, string>("Name1", "Description1"),
                new Tuple <string, string>("Name2", "Description2")
            });

            var reportingInterface = new ReportingInterface();

            using (new SetUser(testData.UserAccount))
            {
                ReportResult reportResult = reportingInterface.RunReport(testData.Report, null);
                Assert.AreEqual(0, reportResult.GridData.Count);
            }
        }
Beispiel #10
0
        public void TestReport_ReportToQueryConverter_Cached( )
        {
            long reportId = Entity.GetByName("AF_String").First( ).Id;

            // Mock IReportToQueryConverter and run again
            Mock <IReportToQueryConverter> mockNonCached = new Mock <IReportToQueryConverter>(MockBehavior.Strict);
            Mock <IReportToQueryConverter> mockCached    = new Mock <IReportToQueryConverter>(MockBehavior.Strict);

            using (var scope = Factory.Current.BeginLifetimeScope(builder => {
                builder.Register(ctx => mockNonCached.Object).Keyed <IReportToQueryConverter>(Factory.NonCachedKey);
                builder.Register(ctx => mockCached.Object).As <IReportToQueryConverter>( );
            }))
                using (Factory.SetCurrentScope(scope))
                {
                    var reportInterface = new ReportingInterface( );

                    IReportToQueryConverter realNonCached = new ReportToQueryConverter( );
                    IReportToQueryConverter realCached    = new CachingReportToQueryConverter(mockNonCached.Object);

                    // Setup
                    mockNonCached
                    .Setup(r2q => r2q.Convert(It.IsAny <Report>( ), It.IsAny <ReportToQueryConverterSettings>( )))
                    .Returns((Report r, ReportToQueryConverterSettings s) => realNonCached.Convert(r, s));

                    mockCached
                    .Setup(r2q => r2q.Convert(It.IsAny <Report>( ), It.IsAny <ReportToQueryConverterSettings>( )))
                    .Returns((Report r, ReportToQueryConverterSettings s) => realCached.Convert(r, s));

                    // First run
                    ReportResult result = reportInterface.RunReport(reportId, null);
                    Assert.That(result, Is.Not.Null);

                    // Second run
                    result = reportInterface.RunReport(reportId, null);
                    Assert.That(result, Is.Not.Null);

                    // Verify
                    mockNonCached
                    .Verify(r2q => r2q.Convert(It.IsAny <Report>( ), It.IsAny <ReportToQueryConverterSettings>( )), Times.Exactly(1));

                    mockCached
                    .Verify(r2q => r2q.Convert(It.IsAny <Report>( ), It.IsAny <ReportToQueryConverterSettings>( )), Times.Exactly(2));
                }
        }
Beispiel #11
0
        public void TestReport_AA_Manager( )
        {
            long reportId = CodeNameResolver.GetInstance("AA_Manager", Report.Report_Type).Single().Id;

            ReportSettings settings = new ReportSettings( );

            settings.RequireFullMetadata          = true;
            settings.SupportPaging                = true;
            settings.PageSize                     = 200;
            settings.RefreshCachedResult          = true;
            settings.RefreshCachedSql             = true;
            settings.RefreshCachedStructuredQuery = true;

            var          reportInterface = new ReportingInterface( );
            ReportResult result          = reportInterface.RunReport(reportId, settings);

            Assert.That(result, Is.Not.Null);
            Assert.That(result.GridData, Has.Count.GreaterThan(0));
        }
        public void ReportingInterface_RunReport_WithSecurity(string reportName)
        {
            BulkPreloader.TenantWarmupIfNotWarm();

            long reportId = reportLookup[reportName];

            using (CacheManager.EnforceCacheHitRules())
            //using (Profiler.Measure("Run report test"))
            {
                ReportingInterface ri = new ReportingInterface();
                ri.RunReport(reportId, new ReportSettings
                {
                    InitialRow           = 0,
                    PageSize             = 1,
                    RequireFullMetadata  = true,
                    RequireBasicMetadata = true
                });
            }
        }
Beispiel #13
0
        public void TestReport_BU_Test( )
        {
            (( CachingQuerySqlBuilder )Factory.QuerySqlBuilder).Clear( );
            (( CachingQueryRunner )Factory.QueryRunner).Clear( );

            long reportId = Entity.GetByName("Business Unit Risks Copy 1").First( ).Id;

            Action action = () =>
            {
                using (new SecurityBypassContext( ))
                {
                    var          reportInterface = new ReportingInterface( );
                    ReportResult result          = reportInterface.RunReport(reportId, null);
                }
            };
            Task task1 = Task.Factory.StartNew(action);

            Task task2 = Task.Factory.StartNew(() => { Thread.Sleep(50); action( ); });

            Task.WaitAll(task1, task2);
        }
Beispiel #14
0
        IEnumerable <IEntity> GetListFromReport(IRunState context, IEntity reportRef)
        {
            var reportSettings = new ReportSettings
            {
                InitialRow      = 0,
                PageSize        = MaxResourcesInList,
                SupportPaging   = true,
                CpuLimitSeconds = EDC.ReadiNow.Configuration.EntityWebApiSettings.Current.ReportCpuLimitSeconds
            };


            var reportingInterface = new ReportingInterface();

            try
            {
                var result = reportingInterface.RunReport(reportRef.Id, reportSettings);
                return(result.GridData.Where(row => row.EntityId > 0).Select(row => Entity.Get(row.EntityId)).ToList());
            }
            catch (TenantResourceLimitException ex)
            {
                throw new WorkflowRunException(ex.CustomerMessage, ex);
            }
        }
Beispiel #15
0
        public void RunReportSomeAccessWithRollup()
        {
            // We will group by the name column but secure by the description column
            // Anything with a D description is allowed
            // This should give 2 groups containing enties the test has access to.
            var nameDescList = new List <Tuple <string, string> >
            {
                new Tuple <string, string>("Name1", "D"),
                new Tuple <string, string>("Name1", "X"),
                new Tuple <string, string>("Name1", "X"),
                new Tuple <string, string>("Name2", "D"),
                new Tuple <string, string>("Name2", "D"),
                new Tuple <string, string>("Name2", "X"),
                new Tuple <string, string>("Name3", "X"),
                new Tuple <string, string>("Name3", "X"),
                new Tuple <string, string>("Name3", "X"),
            };

            // Create the entitues
            SecurityTestData testData = SetupSecurityTest(nameDescList);

            var reportingInterface = new ReportingInterface();

            // Create an access rule only for entities whose description is D
            new AccessRuleFactory().AddAllowReadQuery(testData.UserAccount.As <EntityModel.Subject>(), testData.EntityType.As <EntityModel.SecurableEntity>(),
                                                      TestQueries.EntitiesWithDescription("D", testData.EntityType).ToReport());

            // Get the name column id
            long nameColumnId        = testData.Report.ReportColumns.ToList()[1].Id;
            long descriptionColumnId = testData.Report.ReportColumns.ToList()[2].Id;

            // Create rollup and aggregate settings
            // Group by the name column and apply a count to the description column
            var reportSettings = new ReportSettings
            {
                ReportParameters = new ReportParameters
                {
                    GroupAggregateRules = new ReportMetadataAggregate
                    {
                        IncludeRollup   = true,
                        ShowCount       = true,
                        ShowGrandTotals = true,
                        ShowSubTotals   = true,
                        ShowGroupLabel  = true,
                        ShowOptionLabel = true,
                        Groups          = new List <Dictionary <long, GroupingDetail> >
                        {
                            new Dictionary <long, GroupingDetail>
                            {
                                { nameColumnId, new GroupingDetail {
                                      Style = "groupList"
                                  } }
                            }
                        },
                        Aggregates = new Dictionary <long, List <AggregateDetail> >
                        {
                            { descriptionColumnId, new List <AggregateDetail> {
                                  new AggregateDetail {
                                      Style = "aggCount"
                                  }
                              } }
                        }
                    }
                }
            };

            ReportResult reportResult;

            // Run the report for the test user
            using (new SetUser(testData.UserAccount))
            {
                reportResult = reportingInterface.RunReport(testData.Report, reportSettings);
            }

            // Verify the results
            Assert.AreEqual(nameDescList.Count(i => i.Item2 == "D"), reportResult.GridData.Count);
            Assert.IsTrue(reportResult.GridData.All(d => d.Values[2].Value == "D"));

            // Verify the aggregate data
            List <ReportDataAggregate> aggregateData = reportResult.AggregateData;

            // Two groups + total
            Assert.AreEqual(3, aggregateData.Count);

            ReportDataAggregate name1Agg = aggregateData.First(ad => ad.GroupHeadings[0][nameColumnId].Value == "Name1");
            ReportDataAggregate name2Agg = aggregateData.First(ad => ad.GroupHeadings[0][nameColumnId].Value == "Name2");
            ReportDataAggregate totalAgg = aggregateData.First(ad => string.IsNullOrEmpty(ad.GroupHeadings[0][nameColumnId].Value));

            Assert.AreEqual("1", name1Agg.Aggregates[descriptionColumnId][0].Value);
            Assert.AreEqual("2", name2Agg.Aggregates[descriptionColumnId][0].Value);
            Assert.AreEqual("3", totalAgg.Aggregates[descriptionColumnId][0].Value);
        }
Beispiel #16
0
        /// <summary>
        ///     Export Data for given file format.
        /// </summary>
        /// <param name="reportId">Report Id.</param>
        /// <param name="settings">Report settings</param>
        /// <param name="format">File format.</param>
        /// <returns>ExportInfo</returns>
        public ExportInfo ExportData(long reportId, ReportSettings settings, ExportFormat format)
        {
            var exportInfo = new ExportInfo();

            //set the page size to maximum.
            settings.SupportPaging = true;
            settings.InitialRow    = 0;
            settings.PageSize      = 10001; // The maximum number of records can be exported is limited to 10000.

            //to retrive the report object and run the report, dosen't need the writeable permission.
            var          reportingInterface = new ReportingInterface();
            ReportResult reportResult       = reportingInterface.RunReport(reportId, settings);

            // Ensure that the report result contains the report metadata (which is loaded in a security bypass context).
            // This ensures that when processing the grid data the required metadata is available
            // and will not throw security exceptions.
            var metadata = reportResult.Metadata;

            //Remove the last record if the number of records are more then 10000.
            List <DataRow> rows;

            if (reportResult.GridData.Count > 10000)
            {
                exportInfo.ResponseMessage = "There are more than 10,000 records in this report. Only the first 10,000 records will be downloaded.";
                rows = reportResult.GridData.GetRange(0, 10000);
            }
            else
            {
                rows = reportResult.GridData;
            }

            Stream fileStream;

            // Generate content
            switch (format)
            {
            case ExportFormat.Csv:
            {
                byte[] resultText = ExportToCsv.CreateCsvDocument(reportResult, rows);
                fileStream = new MemoryStream(resultText);
                break;
            }

            case ExportFormat.Excel:
            {
                fileStream = ExportToExcel.CreateExcelDocument(reportResult, rows);
                break;
            }

            case ExportFormat.Word:
            {
                string reportName = Entity.GetName(reportId);
                fileStream = ExportToWord.CreateWordDocument(reportResult, rows, reportName);
                break;
            }

            default:
                throw new ArgumentException("fileFormat");
            }

            //save the file to the database.
            string hash;

            using (fileStream)
            {
                hash = FileRepositoryHelper.AddTemporaryFile(fileStream);
            }
            exportInfo.FileHash = hash;
            return(exportInfo);
        }
Beispiel #17
0
        public void TestReportConditionForCalculatedFieldUnknownType_Bug25079()
        {
            using (new SecurityBypassContext())
            {
                // Get the report root type
                EntityType dogBreedsType = Entity.GetByName <EntityType>("AA_DogBreeds").FirstOrDefault();

                // Build the query and report
                var re = new ResourceEntity(dogBreedsType);

                var structuredQuery = new StructuredQuery
                {
                    RootEntity = re
                };

                // Build id column
                var idColumn = new SelectColumn
                {
                    Expression = new IdExpression
                    {
                        NodeId = re.NodeId
                    },
                    IsHidden    = true,
                    DisplayName = "_id"
                };

                // Build calculated column
                var calcColumn = new SelectColumn
                {
                    Expression = new ReadiNow.Metadata.Query.Structured.ScriptExpression
                    {
                        NodeId     = re.NodeId,
                        Script     = @"iif(iif([Group] = 'Herding', 1, iif([Group] = 'Non-sporting', 2, iif([Group] = 'Scenthound', 3, iif([Group] = 'Terrier', 4, iif([Group] = 'toy', 5, iif([Group] = 'Working', 5, 0)))))) > 4, 'Requires attention', 'On track')",
                        ResultType = new StringType()
                    },
                    DisplayName = "Calc"
                };

                // Add columns to query
                structuredQuery.SelectColumns.Add(idColumn);
                structuredQuery.SelectColumns.Add(calcColumn);

                // Build condition on calc column
                var calcCondition = new QueryCondition
                {
                    Expression = new ColumnReference
                    {
                        ColumnId = calcColumn.ColumnId
                    },
                    Operator = ConditionType.Unspecified,
                    Argument = new TypedValue
                    {
                        Type = new UnknownType()
                    }
                };

                // Add condition to query
                structuredQuery.Conditions.Add(calcCondition);

                // Convert to report and save
                ReadiNow.Model.Report report = structuredQuery.ToReport();
                report.Name = "Test Calc Report " + Guid.NewGuid();
                report.Save();

                // Get strcutured query back so that we have entity ids
                // for structured query elements
                structuredQuery = ReportToQueryConverter.Instance.Convert(report);

                // Add the ad-hoc condition and run the report
                var settings = new ReportSettings
                {
                    ReportParameters = new ReportParameters
                    {
                        AnalyserConditions = new List <SelectedColumnCondition>()
                    },
                    InitialRow = 0,
                    PageSize   = 100
                };

                settings.ReportParameters.AnalyserConditions.Add(new SelectedColumnCondition
                {
                    Operator     = ConditionType.Contains,
                    Value        = "Requires attention",
                    ExpressionId = structuredQuery.Conditions[0].EntityId.ToString(CultureInfo.InvariantCulture),
                    Type         = new StringType()
                });

                var          reportInterface = new ReportingInterface();
                ReportResult result          = reportInterface.RunReport(report, settings);

                // Verify that correct rows are returned
                Assert.IsTrue(result.GridData.All(r => r.Values[0].Value.ToLowerInvariant().Contains(settings.ReportParameters.AnalyserConditions[0].Value.ToLowerInvariant())));
            }
        }
Beispiel #18
0
        public void TestReport_ReportToQueryConverter_WithFauxRelationship_Cached( )
        {
            long reportId       = CodeNameResolver.GetInstance("Template", "Report").Id;
            var  type           = Entity.GetByName <EntityType>("AA_DogBreeds").First();
            long relationshipId = Factory.ScriptNameResolver.GetMemberOfType("AA_All Fields", type.Id, MemberType.Relationship).MemberId;
            long foreignId1     = CodeNameResolver.GetInstance("Test 01", "AA_All Fields").Id;
            long foreignId2     = CodeNameResolver.GetInstance("Test 02", "AA_All Fields").Id;

            ReportSettings settings = new ReportSettings
            {
                ReportRelationship = new ReportRelationshipSettings
                {
                    Direction      = ReportRelationshipSettings.ReportRelationshipDirection.Forward,
                    RelationshipId = relationshipId
                },
                ReportOnType = type.Id
            };

            // Mock IReportToQueryConverter and run again
            Mock <IReportToQueryConverter> mockNonCached = new Mock <IReportToQueryConverter>(MockBehavior.Strict);
            Mock <IReportToQueryConverter> mockCached    = new Mock <IReportToQueryConverter>(MockBehavior.Strict);

            using (var scope = Factory.Current.BeginLifetimeScope(builder =>
            {
                builder.Register(ctx => mockNonCached.Object).Keyed <IReportToQueryConverter>(Factory.NonCachedKey);
                builder.Register(ctx => mockCached.Object).As <IReportToQueryConverter>( );
            }))
                using (Factory.SetCurrentScope(scope))
                {
                    var reportInterface = new ReportingInterface( );

                    IReportToQueryConverter realNonCached = new ReportToQueryConverter( );
                    IReportToQueryConverter realCached    = new CachingReportToQueryConverter(mockNonCached.Object);

                    // Setup
                    mockNonCached
                    .Setup(r2q => r2q.Convert(It.IsAny <Report>( ), It.IsAny <ReportToQueryConverterSettings>( )))
                    .Returns((Report r, ReportToQueryConverterSettings s) => realNonCached.Convert(r, s));

                    mockCached
                    .Setup(r2q => r2q.Convert(It.IsAny <Report>( ), It.IsAny <ReportToQueryConverterSettings>( )))
                    .Returns((Report r, ReportToQueryConverterSettings s) => realCached.Convert(r, s));

                    // First run
                    settings.ReportRelationship.EntityId = foreignId1;
                    ReportResult result = reportInterface.RunReport(reportId, settings);
                    Assert.That(result, Is.Not.Null);
                    Assert.That(result.GridData [0].Values [0].Value, Is.EqualTo("Afghan Hound"));

                    // Second run
                    settings.ReportRelationship.EntityId = foreignId2;
                    result = reportInterface.RunReport(reportId, settings);
                    Assert.That(result, Is.Not.Null);
                    Assert.That(result.GridData [0].Values [0].Value, Is.EqualTo("Australian Cattle Dog"));

                    // Verify
                    mockNonCached
                    .Verify(r2q => r2q.Convert(It.IsAny <Report>( ), It.IsAny <ReportToQueryConverterSettings>( )), Times.Exactly(1));

                    mockCached
                    .Verify(r2q => r2q.Convert(It.IsAny <Report>( ), It.IsAny <ReportToQueryConverterSettings>( )), Times.Exactly(2));
                }
        }