简体   繁体   中英

Mocking a method return inside tested method

so I am trying to write an unit test for this method (I'm using xUnit and MOQ):

public override FilteredFeedPagesResult<ProgramPage> Create(FilteredFeedContext context)
{
    var pages = _pageFilteringService.GetFilteredFeedPages(
            context.Reference,
            context.Culture,
            context.Filters,
            _customPageFilter);

    if (context.IsSortedByDate && context.PageType.Name is nameof(ProgramPage))
    {
        var sortedPages = pages.OfType<ProgramPage>()
                .Select(page => new
                {
                    Page = page,
                    ScheduledStartDate = page.GetProgramPairings(page).Select(pairing => pairing.ScheduledStartDate).DefaultIfEmpty(DateTime.MaxValue).Min(),
                })
                .OrderBy(item => item.ScheduledStartDate)
                .ThenBy(item => item.Page.Name)
                .Select(item => item.Page);

        return Map(sortedPages, context.PageNumber, context.PageSize);
    }

    return Map(pages.OrderByDescending(x => x.Date), context.PageNumber, context.PageSize);
}

As you can see, inside the LINQ statement in if clause there is a GetProgramPairings being invoked. It is supposed to get events for particular page from the database: Then, based on it, the order of events is created.

Code of the GetProgramPairings method:

public IEnumerable<ProgramPairing> GetProgramPairings(ProgramPage page)
{
    var pairings = new List<ProgramPairing>();
    
    if (page != null && page.ProgramPairings != null && page.ProgramPairings.FilteredItems.Any())
    {
        foreach (ContentAreaItem item in page.ProgramPairings.FilteredItems)
        {
            if (contentLoader.Service.TryGet<ProgramPairing>(item.ContentLink, out ProgramPairing pairing))
            {
                pairings.Add(pairing);
            }
        }
    }
    
    return pairings;
}

This is what my test looks like so far:

[Fact]
public void Create_IsSortedByDateTrueAndPageTypeProgramPage_ReturnsSortedPages()
{
    var homePageMock = SetupHomePage();

    var returnedPages = new[] { CreateProgramPage(DateTime.UtcNow.AddDays(-5)), CreateProgramPage(DateTime.UtcNow) };

    var context = new FilteredFeedContext(homePageMock.Object, 0, 6, typeof(ProgramPage), null, null, true);

    _filteredFeedPagesFilteringServiceMock.Setup(x => x.GetFilteredFeedPages<ProgramPage>(It.Is<ContentReference>(p => p.ID == homePageMock.Object.ContentLink.ID), It.Is<CultureInfo>(c => c.LCID == homePageMock.Object.Language.LCID), It.IsAny<IDictionary<string, string>>(), It.IsAny<IPageCustomFilter<ProgramPage>>()))
        .Returns(returnedPages);

    var result = _sut.Create(context);

    //will need to create an assert to check if items in the list are in right order
}

My question is, how to mock the IEnumerable parings returned fromGetProgramPairings inside of the main method being tested?

The problem here is the Single Responsibility Principle. Think thoroughly, is the ProgramPage's responsibility to get program pairings? This logic should be encapsulated in some other service. Once you do that, you can easily mock that service. Good luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM