简体   繁体   中英

Moq setup for interface with function argument

I want to write an UnitTest with Moq 4.14.7. The method to be tested is as follows:

public IFoo Get(Guid id)
{
    Func<IFoo> getData = () => _repository.Get(id);
    if (_cache.TryGetAndSet(vaultId, getData, out var result))
    {
        return result;
    }
}

To briefly explain. I have a generic cache class. It checks in the cache if an entity with the passed guid exists. If this is not the case, the repository is called.

Now I have the following setup for the cache:

_cache.Setup
(
    x => x.TryGetAndSet
    (
        _vaultId,
        It.IsAny<Func<IFoo>>(),
        out foo
    )
)
.Returns(true);

The test works so far, but I do not achieve 100% coverage with it, because the func is not covered.

Is there a better way here than to work with It.IsAny and get 100% coverage?

Capture the arguments passed to the member and invoke the function as desired.

//...

IFoo mockedFoo = Mock.Of<IFoo>();

IFoo foo = null;

_repo.Setup(_ => _.Get(It.IsAny<Guid>()).Returns(mockedFoo);

_cache
    .Setup(_ => _.TryGetAndSet(It.IsAny<Guid>(), It.IsAny<Func<IFoo>>(), out foo))
    .Returns((Guid vid, Func<IFoo> func, IFoo f) => {
        foo = func(); //<-- invoke the function and assign to out parameter.
        return true;
    });

//...

//Assertion can later verify that the repository.Get was invoked
//Assertion can later assert that foo equals mockedFoo

TryGetAndSet will return true , and the out argument will return the mockedFoo, lazy evaluated

Reference Moq Quickstart

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