Unit test with Moq callback anonymous function I have the following unit test that is testing predicate logic in a repository (Note: mockOpportunityRepository.Setup):

[Test]
public void GetFollowedByUserIdShouldGetTheUsersFollowedOpportunitiesFromOpportunityFollowRepositoryAndThenGetThoseFollowedOpportunities()
{
    const int ExpectedOpportunityId = 9;

    var testOpportunities = new List&lt;Domain.EF.Opportunity&gt;()
    {
        OpportunityBuilder.Default().WithId(1).Build(),
        OpportunityBuilder.Default().WithId(2).Build(),
        OpportunityBuilder.Default().WithId(ExpectedOpportunityId).Build(),
    };

    var actualOpportunities = new List&lt;Opportunity&gt;();

    var expectedOpportunityFollows = new List&lt;OpportunityFollow&gt; { new OpportunityFollow { OpportunityFollowId = 1, OpportunityId = ExpectedOpportunityId, UserId = UserId } };
    mockOpportunityFollowRepository.Setup(x =&gt; x.GetByUserId(UserId)).ReturnsAsync(expectedOpportunityFollows);

    mockOpportunityRepository.Setup(
        s =&gt;
            s.GetAsync(
                It.IsAny&lt;Expression&lt;Func&lt;Domain.EF.Opportunity, bool&gt;&gt;&gt;(),
                It.IsAny&lt;Func&lt;IQueryable&lt;Domain.EF.Opportunity&gt;, IOrderedQueryable&lt;Domain.EF.Opportunity&gt;&gt;&gt;(),
                It.IsAny&lt;int?&gt;(),
                It.IsAny&lt;int&gt;()))
        .Callback&lt;
            Expression&lt;Func&lt;Domain.EF.Opportunity, bool&gt;&gt;,
            Func&lt;IQueryable&lt;Domain.EF.Opportunity&gt;,
            IOrderedQueryable&lt;Domain.EF.Opportunity&gt;&gt;,
            int?,
            int&gt;((queryParam, sortParam, takeParam, skipParam) =&gt;
            {
                var func = queryParam.Compile();
                actualOpportunities = testOpportunities.Where(func).ToList();
            });

    var results = sut.GetFollowedByUserId(UserId);

    mockOpportunityFollowRepository.Verify(x =&gt; x.GetByUserId(UserId), Times.Once);
    actualOpportunities.Count.Should().Equals(1);
    actualOpportunities[0].OpportunityId.Should().Equals(ExpectedOpportunityId);
}


I have several tests like this all utilising the same bulky mockOpportunityRepository.Setup and wanted to refactor it into one re-useable place. Essentially the setup has a callback which runs an anonymous function. The anon function compiles the query parameters and executes them against a test list of opportunities. The outer test function needs the result of this filter to Assert the predicate logic.

If I try to move the mockOpportunityRepository.Setup into a separate function and try to output the actualOpportunities by reference I get a compiler error that ref and out parameters are not allowed in anonymous method body. I'm not very knowledgeable on functions and am sure it can be done.

Can anyone refactor this and suggest a way of moving the mockOpportunityRepository.Setup out of the test to make it reusable yet somehow get the results of the anonymous function (actualOpportunities) back to the calling test?
I think, for what it's worth, you have mostly only succeeded in testing your mocks here.  Even if you moved these mocks out of the test, I think you'd still only be testing your mock implementation and not much production code. So these tests can pass all day long without reflecting the condition of your production implementations.  (If I'm understanding every properly :)

[Test]
public void GetFollowedByUserIdShouldGetTheUsersFollowedOpportunitiesFromOpportunityFollowRepositoryAndThenGetThoseFollowedOpportunities()
{
    const int ExpectedOpportunityId = 9;

    var testOpportunities = new List&lt;Domain.EF.Opportunity&gt;()
    {
        OpportunityBuilder.Default().WithId(1).Build(),
        OpportunityBuilder.Default().WithId(2).Build(),
        OpportunityBuilder.Default().WithId(ExpectedOpportunityId).Build(),
    };

    var actualOpportunities = new List&lt;Opportunity&gt;();

    var expectedOpportunityFollows = new List&lt;OpportunityFollow&gt; { new OpportunityFollow { OpportunityFollowId = 1, OpportunityId = ExpectedOpportunityId, UserId = UserId } };
    mockOpportunityFollowRepository.Setup(x =&gt; x.GetByUserId(UserId)).ReturnsAsync(expectedOpportunityFollows);

    mockOpportunityRepository.Setup(
        s =&gt;
            s.GetAsync(
                It.IsAny&lt;Expression&lt;Func&lt;Domain.EF.Opportunity, bool&gt;&gt;&gt;(),
                It.IsAny&lt;Func&lt;IQueryable&lt;Domain.EF.Opportunity&gt;, IOrderedQueryable&lt;Domain.EF.Opportunity&gt;&gt;&gt;(),
                It.IsAny&lt;int?&gt;(),
                It.IsAny&lt;int&gt;()))
        .Callback&lt;
            Expression&lt;Func&lt;Domain.EF.Opportunity, bool&gt;&gt;,
            Func&lt;IQueryable&lt;Domain.EF.Opportunity&gt;,
            IOrderedQueryable&lt;Domain.EF.Opportunity&gt;&gt;,
            int?,
            int&gt;((queryParam, sortParam, takeParam, skipParam) =&gt;
            {
                var func = queryParam.Compile();
                actualOpportunities = testOpportunities.Where(func).ToList();
            });

    // NOTE: not sure which guy your sut variable is here.  
    // NOTE: no assertions on the results is suspect.
    var results = sut.GetFollowedByUserId(UserId);

    // NOTE: this is testing the plumbing of a function.  that my thing called another thing.  in general, 
    //       i have found this kind of testing to be less valuable and brittle.  if the function
    //       can do the job without calling the other thing in the future, this test will break,
    //       even though the function works properly. ymmv.
    mockOpportunityFollowRepository.Verify(x =&gt; x.GetByUserId(UserId), Times.Once);

    // NOTE: unfortunately, all thats tested here is that the mock implementation returns
    //       the right result.  no production code is exercised for these.
    actualOpportunities.Count.Should().Equals(1);
    actualOpportunities[0].OpportunityId.Should().Equals(ExpectedOpportunityId);
}


For all the mocking etc... I believe the above code is functionally equivalent as what I have below (or close to it).  And almost all of it is still mock implementation.  What production code we are testing is hard to know.

[Test]
public void GetFollowedByUserIdShouldGetTheUsersFollowedOpportunitiesFromOpportunityFollowRepositoryAndThenGetThoseFollowedOpportunities()
{
    const int ExpectedOpportunityId = 9;

    var testOpportunities = new List&lt;Domain.EF.Opportunity&gt;()
    {
        OpportunityBuilder.Default().WithId(1).Build(),
        OpportunityBuilder.Default().WithId(2).Build(),
        OpportunityBuilder.Default().WithId(ExpectedOpportunityId).Build(),
    };

    Expression&lt;Func&lt;Domain.EF.Opportunity, bool&gt;&gt; queryParam; // = ???

    var actualOpportunities = new List&lt;Opportunity&gt;();
    var func = queryParam.Compile();

    actualOpportunities = testOpportunities.Where(func).ToList();

    actualOpportunities.Count.Should().Equals(1);
    actualOpportunities[0].OpportunityId.Should().Equals(ExpectedOpportunityId);
}   


You could consider this to be more of an integration test.  But then what's being tested?  That entity framework works?  Or SQL?  If so, these fall significantly outside of the boundaries of what a unit test can do well for you.  

For my money it's an integration test and needs to exercise production code.  I think you can safely remove this test as a unit test.