As you correctly spotted, there are distinct methods SetupGet and SetupSet to initialize getters and setters respectively. Although SetupGet is intended to be used for properties, not indexers, and will not allow you handling key passed to it. To be precise, for indexers SetupGet will call Setup anyway:
internal static MethodCallReturn<T, TProperty> SetupGet<T, TProperty>(Mock<T> mock, Expression<Func<T, TProperty>> expression, Condition condition) where T : class
{
return PexProtector.Invoke<MethodCallReturn<T, TProperty>>((Func<MethodCallReturn<T, TProperty>>) (() =>
{
if (ExpressionExtensions.IsPropertyIndexer((LambdaExpression) expression))
return Mock.Setup<T, TProperty>(mock, expression, condition);
...
}
...
}
To answer your question, here is a code sample using underlying Dictionary to store values:
var dictionary = new Dictionary<string, object>();
var applicationSettingsBaseMock = new Mock<SettingsBase>();
applicationSettingsBaseMock
.Setup(sb => sb[It.IsAny<string>()])
.Returns((string key) => dictionary[key]);
applicationSettingsBaseMock
.SetupSet(sb => sb["Expected Key"] = It.IsAny<object>())
.Callback((string key, object value) => dictionary[key] = value);
As you can see, you have to explicitly specify key to set up indexer setter. Details are described in another SO question: Moq an indexed property and use the index value in the return/callback