我使用FakeItEasy模拟了MVC控制器中的Session对象:
var session = A.Fake<HttpSessionStateBase>();
A.CallTo(() => session["SomeKey"]).Returns("SomeValue");
Controller.ControllerContext = new ControllerContext(mockHttpContext, new RouteData(), Controller);
如果您在控制器操作中访问session-object,它将返回正确的值:
public ActionResult Index()
{
var value = Session["Key"]; // value = "SomeValue" like it is supposed to
...
}
稍后在控制器中出现问题,通过这样的setter使用相同的密钥设置会话:
Session["Key"] = "SomeOtherValue";
然后当使用该键时,它返回错误的值:
var value = Session["Key"]; // value = "Key"
模拟会话不再返回我的模拟值,它也不返回新值,而是返回键(WTF ?!)。我究竟做错了什么?使用setter时,模拟对象实际发生了什么?
答案 0 :(得分:3)
我认为我们这里有一个功能请求的饲料。 (我已经做了一个:issue 277。) 我认为使用getter和setter的未配置索引属性存储值并稍后返回它是合理的。
更新:问题277已在FakeItEasy 1.21.0中修复。从NuGet获取它(或更新的版本)。
与此同时,您可以解决类似这个我在调用原始方法时指出问题后所做的新示例:
[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");
}
答案 1 :(得分:2)
一个突出的问题可能是:在这种情况下什么是正确的价值?对于您是否希望此索引器的行为类似于模拟或真正的索引器,您似乎存在冲突。首先配置一个带有固定值的mock来返回,然后你写入索引器,即使你没有嘲笑它。那么FakeItEasy应该如何处理书面价值呢?它现在应该返回你告诉它返回的模拟值,还是应该知道你现在意味着新值?怎么知道?
你既不会得到旧值也不会得到新值这一事实有点奇怪,但看看HAL 9000在给出相互矛盾的指令时发生了什么!这可能表明您需要采用不同的方法。
您是否考虑过使用其他设置,例如ReturnsNextFromSequence()
或ReturnsLazily()
?