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

时间:2014-03-22 12:20:37

标签: 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);
    }

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
    }

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");

1 个答案:

答案 0 :(得分:0)

以下是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);

您收到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();
        }));

请注意Return(null)已经不再需要了。您唯一需要做的就是将lambda显式转换为stubbed方法签名。

希望有所帮助。