Razzie
Razzie

Reputation: 31222

Return a value based on other method input

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:

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

Answers (2)

CodeCaster
CodeCaster

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

Steve Danner
Steve Danner

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

Related Questions