Checking function calls with anonymous functions in parameters

I have a class, a service, and two interfaces:

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

Using RhinoMocks, I want to make sure that when MyBasicObjectService.GetByName("AnUniqueName") is executed, CacheProvider.Get("AnUniqueName", () => MyBasicObjectRepository.GetByName("AnUniqueName")) . I have a fixture configured like this:

 [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>("AnUniqueName", () => repo.GetByName("AnUniqueName"))); mock.ReplayAll(); // Act var result = service.GetByName("AnUniqueName"); // Assert mock.VerifyAll(); } } 

I would expect this test to pass, but at the start this statement fails, telling me that the function outlined in cacheProvider.Expect is not called. Did I miss something. bullying and testing methods that accept Func parameters <

Edit:

So if I do:

 cacheProvider.Expect(p => p.Get<MyBasicObject>("AnUniqueName", () => repo.GetByName("AnUniqueName"))).IgnoreArguments(); 

(i.e. add the IgnoreArguments () method at the end of the pending call)

... the test is just fine. I assume this is a problem with the argument passed. Is there something that I am doing wrong while waiting for the cache provider method to call, but it is choking on the anonymous method that is being passed to?

+4
source share
2 answers

The problem is that two anonymous methods (one from Expect and one created in GetByName ) are two different objects and therefore not equal. You can fix this by partially matching arguments like this

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

What I finished for the test was:

 [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(); } } 

This works specifically for my use case (causing the database to be retrieved in case of a cache miss and making sure that the service uses the correct repository call at that moment), but this is kind of not very wonderful work if you do not plan to immediately use anonymous function. I am sure there are other alternatives with .WenCalled, but now this works for me.

0
source

Source: https://habr.com/ru/post/1496915/


All Articles