Tim Long has the right of it. What is the "right value"? However, returning the key is weird behaviour.
I think we have fodder for a feature request in here. (And I've made one: issue 277.) I think it would be reasonable for unconfigured indexed properties with getters and setters to store values and return them later.
Update: issue 277 has been fixed in FakeItEasy 1.21.0. Get it (or a newer version) from NuGet.
In the meantime, you can workaround with something like this new example I made after you pointed out the problem with calling the original methods:
[Test]
public void TestItemProperty()
{
var mySession = new Dictionary<string, object>();
var session = A.Fake<HttpSessionStateBase>();
A.CallTo(session)
.Where(call => call.Method.Name == "set_Item")
.Invokes((string key, object value) => mySession[key] = value);
A.CallTo(() => session[A<string>._])
.ReturnsLazily((string key) => mySession[key]);
A.CallTo(() => session["key1"]).Returns("value1");
A.CallTo(() => session["key1"]).Returns("value1");
Assert.That(session["key1"], Is.EqualTo("value1"));
session["key2"] = "value2";
Assert.That(session["key2"], Is.EqualTo("value2"));
Assert.That(session["key1"], Is.EqualTo("value1"), "second go");
}