Reputation: 31222
I'm trying to mock a very simple (simplified) interface which basically is an interface for a Cache service:
public interface ICache
{
T Get<T>(String key);
T Set<T>(String key, T value); // return T on success or null on fail
}
I want to mock this using Moq the following way:
Get
with a key that has not been set yet, it should return null
Set
with a key 'x' and value 'y', and then call Get
with
key 'x', it should return 'y'Get
with key 'x', it should return the new value 'z' and not 'y'.I know I could create a fake object that implements the interface and which uses a Dictionary, but I was wondering if this can be done easily using Moq. Thanks!
Upvotes: 4
Views: 800
Reputation: 151586
You can do that with callbacks that access a dictionary:
var dictionary = new Dictionary<string, object>();
var mock = new Mock<ICache>(MockBehavior.Strict);
mock.Setup(c => c.Set(It.IsAny<string>(), It.IsAny<object>()))
.Callback((string k, object v) => dictionary[k] = v)
.Returns((string k, object v) => v);
mock.Setup(c => c.Get<object>(It.IsAny<string>()))
.Returns((string k) => dictionary.ContainsKey(k) ? dictionary[k] : null);
const string fooString = "foo";
const string barString = "bar";
mock.Object.Set(fooString, (object)barString);
var bar = mock.Object.Get<object>(fooString);
Assert.AreEqual(barString, bar);
But that isn't reusable as you'll have to copypaste it for each test that does something like this.
A fake in which you encapsulate this behavior seems to be the way to go.
Upvotes: 4
Reputation: 22148
To me, the behavior you are describing implies an underlying dictionary. But for a simple unit test, I would probably just call Setup
twice to manage those expectations.
mockCache.Setup(c => c.Get(It.Is<string>(x))).Returns(y);
//...other code
mockCache.Object.Set(x, z);
mockCache.Setup(c => c.Get(It.Is<string>(x)).Returns(z);
//...other code
Upvotes: 4