C# 使用参数中的匿名函数验证函数调用

C# 使用参数中的匿名函数验证函数调用,c#,rhino-mocks,anonymous-function,C#,Rhino Mocks,Anonymous Function,我有一个类、一个服务和两个接口: public class MyBasicObject { public MyBasicObject() { } public int Id { get; set; } public string Name { get; set; } } public interface ICacheProvider { T Get<T>(string key, Func<T> fetcher) wher

我有一个类、一个服务和两个接口:

public class MyBasicObject
{
    public MyBasicObject() { }

    public int Id { get; set; }        
    public string Name { get; set; }
}

public interface ICacheProvider
{
    T Get<T>(string key, Func<T> fetcher) where T:class;
}

public interface IMyBasicObjectRepository
{
    MyBasicObject GetByName(string name);
}

public class MyBasicObjectService
{
    public MyBasicObjectService(ICacheProvider cacheProvider, 
                                IMyBasicObjectRepository repository)
    {
        CacheProvider = cacheProvider;
        MyBasicObjectRepository = repository;
    }

    public ICacheProvider CacheProvider { get; set; }
    public IMyBasicObjectRepository MyBasicObjectRepository { get; set; }

    public MyBasicObject GetByName(string name)
    {
        return CacheProvider.Get<MyBasicObject>(name, () =>
                                MyBasicObjectRepository.GetByName(name));
    }
}
我希望这个测试能够通过,但运行时,断言失败,通知我,
cacheProvider.expect中的函数没有被调用。我错过了什么吗。采用Func参数的模拟和测试方法

编辑:

因此,如果我这样做:

cacheProvider.Expect(p => p.Get<MyBasicObject>("AnUniqueName", () => repo.GetByName("AnUniqueName"))).IgnoreArguments();
cacheProvider.Expect(p=>p.Get(“AnUniqueName”),()=>repo.GetByName(“AnUniqueName”)).IgnoreArguments();
(也就是说,将IgnoreArguments()方法添加到expect调用的末尾)


…测试通过得很好。我假设,这是一个问题的论点传递。在expect中是否有我做错的事情,缓存提供程序方法被调用,但它被传入的匿名方法阻塞了?

问题是这两个匿名方法(在
Expect
中的一个对象和在
GetByName
中创建的一个对象是两个不同的对象,因此不相等。可以通过如下方式部分匹配参数来解决此问题:

cacheProvider.Expect(p => p.Get<MyBasicObject>(Arg<string>.Is.Equal("AnUniqueName"), Arg <Func<MyBasicObject>>.Is.NotNull));
cacheProvider.Expect(p=>p.Get(Arg.Is.Equal(“AnUniqueName”),Arg.Is.NotNull));

我最后为测试做的是:

[TestFixture]
public class MyBasicObjectServiceFixture
{
    [Test]
    public void GetByNameShouldCallCacheProviderFunction()
    {
        // Arrange
        MockRepository mock = new MockRepository();
        IMyBasicObjectRepository repo = mock.DynamicMock<IMyBasicObjectRepository>();
        ICacheProvider cacheProvider = mock.DynamicMock<ICacheProvider>();
        MyBasicObjectService service = new MyBasicObjectService(cacheProvider, repo);

        cacheProvider.Expect(p => p.Get<MyBasicObject>(Arg<string>.Is.Equal("AnUniqueName"), Arg<Func<MyBasicObject>>.Is.NotNull))
                .WhenCalled(call => 
                    {
                        var repoCall = (Func<MyBasicObject>)call.Arguments[1];
                        repoCall.Invoke();
                    });
            repo.Expect(c => c.GetByName("AnUniqueName"));

        mock.ReplayAll();

        // Act
        var result = service.GetByName("AnUniqueName");

        // Assert
        mock.VerifyAll();
    }
}
[TestFixture]
公共类MyBasicObjectServiceFixture
{
[测试]
public void GetByNameShouldCallCacheProviderFunction()
{
//安排
MockRepository mock=新建MockRepository();
imybasicobjectrepo=mock.DynamicMock();
ICacheProvider cacheProvider=mock.DynamicMock();
MyBasicObjectService=新的MyBasicObjectService(cacheProvider,repo);
Expect(p=>p.Get(Arg.Is.Equal(“AnUniqueName”),Arg.Is.NotNull))
.何时呼叫(呼叫=>
{
var repoCall=(Func)call.Arguments[1];
repoCall.Invoke();
});
回购预期(c=>c.GetByName(“AnUniqueName”);
mock.ReplayAll();
//表演
var result=service.GetByName(“AnUniqueName”);
//断言
mock.VerifyAll();
}
}

这特别适用于我的用例(在缓存未命中的情况下调用数据库检索,并确保服务在当时使用正确的存储库调用),但如果您不打算立即调用匿名函数,这就不是一个很好的解决方法。我确信有其他方法可以使用。when called,但就目前而言,这对我来说是有效的。

我想在这种情况下,我的问题是-是否有任何可能的方法断言匿名函数以匹配方式传递服务上的函数是什么?我意识到两个匿名函数永远不会相等,但我正在努力找出一种可以进行单元测试的方法来确保服务上的匿名函数是正确的。有什么想法吗?(在一个实现中,服务将调用缓存提供程序,在缓存未命中的情况下,执行传入的匿名函数。我想我可以专门为单元测试执行缓存提供程序的实现,然后断言,在缓存未命中的情况下,调用存储库方法-这是正确的做法吗事实上,我需要一个ICacheProvider的实现,它无论如何都会绕过缓存。)为我最终所做的添加了一个答案。
[TestFixture]
public class MyBasicObjectServiceFixture
{
    [Test]
    public void GetByNameShouldCallCacheProviderFunction()
    {
        // Arrange
        MockRepository mock = new MockRepository();
        IMyBasicObjectRepository repo = mock.DynamicMock<IMyBasicObjectRepository>();
        ICacheProvider cacheProvider = mock.DynamicMock<ICacheProvider>();
        MyBasicObjectService service = new MyBasicObjectService(cacheProvider, repo);

        cacheProvider.Expect(p => p.Get<MyBasicObject>(Arg<string>.Is.Equal("AnUniqueName"), Arg<Func<MyBasicObject>>.Is.NotNull))
                .WhenCalled(call => 
                    {
                        var repoCall = (Func<MyBasicObject>)call.Arguments[1];
                        repoCall.Invoke();
                    });
            repo.Expect(c => c.GetByName("AnUniqueName"));

        mock.ReplayAll();

        // Act
        var result = service.GetByName("AnUniqueName");

        // Assert
        mock.VerifyAll();
    }
}