简体   繁体   中英

C# Moq Unit Testing with Lambda Expression or Func delegate

I am using Moq with C# for unit testing.

I have the following implementation to test:

var jobsSelectionToMapJobModel = new List<Job>();
var jobsSelectionToMapDataTableModel =
                _enumerableWrapperService.Select(jobsSelectionToMapJobModel,
                    x => _convertJobToJobsModelForDataTableService.Convert(umbracoHelper, x));

The Select Method in _enumerableWrapperService.Select() has the following signature, like the Linq one:

Enumerable<TResult> Select<TSource, TResult>(IEnumerable<TSource> source,
            Func<TSource, TResult> selector);

I would like to test out that the selector Func delegate's content has the correct logic set in it. The umbracoHelper variable is an external paramater passed on to this method.

If you use the It.IsAny<Func<TSource, TResult>>() , we will not be asserting that the logic is fine. On the other hand, I was thinking of using something like It.Is<Func<TSource,TResult>(func => XXXXXXXX) , but cannot figure out how to make it work

See below examples:

UNIT TEST EXAMPLE 1

_listToReturn= new List<JobsModelForDataTable>();
_listOfJobs= new List<Job>();
GetMockFor<IEnumerableWrapperService>()
                .Setup(x => x.Select(_listOfJobs,
                     It.IsAny<Func<Job, JobsModelForDataTable>>()))
                .Returns(_listToReturn);

//The problem with the above is that you are not asserting the correct logic as it accepts any Func which has that same signature

UNIT TEST EXAMPLE 2

 _listToReturn= new List<JobsModelForDataTable>();
_listOfJobs= new List<Job>();
GetMockFor<IEnumerableWrapperService>()
                .Setup(x => x.Select(_listOfJobs,
                     It.Is<Func<Job, JobsModelForDataTable>>(f => ......)))
                .Returns(_listToReturn);

//This might be an option but I cannot figure out how to make it work

Or maybe we need to rethink what we are doing in another way?

I would appreciate any help on this, on how I can test it out.


Thank you in advance for your help.

It is rather difficult if not practically impossible to check programmatically whether two expressions do the same thing. So your best bet is to move the expression into a regular, named method and test that method:

var jobsSelectionToMapJobModel = new List<Job>();
var jobsSelectionToMapDataTableModel =
                _enumerableWrapperService.Select(jobsSelectionToMapJobModel, ActualMethodToTest);

[...]

internal Something ActualMethodToTest( Job x ) => _convertJobToJobsModelForDataTableService.Convert( _umbracoHelper, x );

and the write a test for ActualMethodToTest , probably using Moq-mocks for convertJobToJobsModelForDataTableService and umbracoHelper . And, of course, a test for _enumerableWrapperService 's Select .

Maybe the Callback function can be helpful in this case

Func<List<Job>, Job> umbracoHelper = lj => lj.First(); // or any other selection method...
        var listToReturn = new List<JobsModelForDataTable>();
        var listOfJobs = new List<Job>();
        new Mock<IEnumerableWrapperService>().Setup(x => x.Select(listOfJobs, It.IsAny<Func<Job, JobsModelForDataTable>>()))
                                             .Callback<List<Job>, Func<Job, JobsModelForDataTable>>((j, fj) => fj(umbracoHelper(j)))
                                             .Returns(listToReturn);

And if you use a mock also for _convertJobToJobsModelForDataTableService you can verify it

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