1

我已经使用 FakeItEasy 模拟了 MVC 控制器中的会话对象,方法是:

var session = A.Fake<HttpSessionStateBase>();
A.CallTo(() => session["SomeKey"]).Returns("SomeValue");

Controller.ControllerContext = new ControllerContext(mockHttpContext, new RouteData(), Controller);

如果您在控制器操作中访问会话对象,它将返回正确的值:

public ActionResult Index()
{
    var value = Session["Key"]; // value = "SomeValue" like it is supposed to

    ...
}

稍后会在控制器中出现问题,其中会话是通过这样的设置器使用相同的键设置的:

Session["Key"] = "SomeOtherValue";

然后当使用密钥时,它返回错误的值

var value = Session["Key"]; // value = "Key" 

模拟会话不再返回我的模拟值,也不再返回新值,而是返回键(WTF?!)。我究竟做错了什么?当使用 setter 时,模拟对象实际上会发生什么?

4

2 回答 2

3

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");
}
于 2014-03-20T00:52:02.333 回答
2

一个突出的问题可能是:在这种情况下,正确的价值是什么?您似乎对是否希望此索引器表现得像一个模拟或真正的索引器有冲突。您首先使用固定值配置模拟以返回,然后写入索引器,即使您没有模拟它。那么 FakeItEasy 应该如何处理书面价值呢?它现在应该返回您告诉它返回的模拟值,还是应该以某种方式知道您现在的意思是新值?它是怎么知道的?

您既没有得到旧值也没有得到新值这一事实有点奇怪,但看看 HAL 9000 在收到相互冲突的指令时发生了什么!这可能表明您需要不同的方法。

Have you considered using a different setup, such as ReturnsNextFromSequence() or ReturnsLazily()?

于 2014-03-19T16:49:37.240 回答