单元测试RhinoMocks中的回调函数Func <T>

rda*_*pan 5 c# rhino-mocks

我一直试图弄清楚如何覆盖从缓存中获取项目时用作回调的内部函数.我有一个接受密钥和Func的CacheService.当项目不在缓存中时,将调用Func.

此示例代码基于SO中的其他建议,但cacheService.Get方法始终返回null并且从未调用过WhenCalled.

我理解它应该覆盖这个内部方法的争议,但是为了开始我尝试可能的方法来覆盖这个而不为这个内部方法创建一个新类.感谢您的帮助.

CacheService.cs

    public T Get<T>(string key, Func<T> funcWhenNotExist)
    {
        if (!Exists(key))
        {
            var result = funcWhenNotExist();
            Cache.Put(key, result);
        }

        return DoSomethingWithRetry(() => (T)Cache.Get(key), MAXRETRY);
    }
Run Code Online (Sandbox Code Playgroud)

SomeService.cs

    public SomeDto GetSomeDto(string dtoAlias)
    {
           string cacheKey = "whatever";
           var someDto = cacheService.Get(cacheKey, () => GetSomeDtoInternal(dtoAlias));

           return someDto
    }

    internal SomeDto GetSomeDtoInternal(string dtoAlias
    {
    //do more here
    }
Run Code Online (Sandbox Code Playgroud)

SomeServiceTest.cs

    // Arrange
        SomeDto stubResult = new SomeDto();
        cacheService.Stub(s => s.Get(Arg<string>.Is.Anything, Arg<Func<SomeDto>>.Is.Anything)).WhenCalled(m =>
        {
            var func = (Func<SomeDto>) m.Arguments[1];
            stubResult = func();
        }).Return(stubResult);

        // Act
        var result = service.GetSomeDto("whateveralias");
Run Code Online (Sandbox Code Playgroud)

Ale*_*iuk 1

这是存根的一个工作示例CacheService

cacheService
    .Stub(s => s.Get(Arg<string>.Is.Anything, Arg<Func<SomeDto>>.Is.Anything))
    .WhenCalled(m =>
        {
            var func = (Func<SomeDto>)m.Arguments[1];
            m.ReturnValue = func();
        })
    .Return(null);
Run Code Online (Sandbox Code Playgroud)

你之所以得到,null是因为m.ReturnValue没有设置。所以默认使用一个值来返回。
Return()WhenCalled()使用时参数会被忽略 - 这经常令人困惑。

这里还有一个有点不同的解决方案:
我个人更喜欢使用Do()处理程序而不是WhenCaled()在类似的情况下。它允许以类型安全的方式编写存根处理程序:

cacheService
    .Stub(s => s.Get(Arg<string>.Is.Anything, Arg<Func<SomeDto>>.Is.Anything))
    .Do((Func<string, Func<SomeDto>, SomeDto>)((key, funcWhenNotExist) =>
        {
            return funcWhenNotExist();
        }));
Run Code Online (Sandbox Code Playgroud)

请注意,Return(null)这里不再需要了。您唯一需要做的就是将 lambda 显式转换为存根方法签名。

希望有帮助。