Ответ 1
Причина, по которой обратный вызов используется в вызове SetupGet, заключается в том, что ссылка _sessionReport передается по значению, это означает, что последующий вызов метода Set не будет обновлять значение, возвращаемое методом get.
Чтобы узнать, что происходит более четко. Если вы настроили свой макет следующим образом: -
SessionData.SetupSet(s => s.Report = It.IsAny<Report>());
SessionData.SetupGet(s => s.Report).Returns(_report);
В псевдокоде реализация Mocked будет немного похожа на
public Report Report {
set { }
get {
// Copy of the value of the _report reference field in your test class
return _reportCopy;
}
}
Так что делать что-то подобное не получится: -
ISessionData session = SessionData.Object
Report report = new Report();
session.Report = report;
session.Report.ShouldEqual(report); //Fails
_report.ShouldEqual(report); // Fails
Очевидно, нам нужно добавить какое-то поведение к методу Set, поэтому мы настроим Mock так:
SessionData.SetupSet(s => s.Report = It.IsAny<Report>())
.Callback(s => _report = s);
SessionData.SetupGet(s => s.Report).Returns(_report);
Это приводит к реализации Mocked, немного похожей на
public Report Report {
set {
// Invokes delegate that sets the field on test class
}
get {
// Copy of the original value of the _report reference field
// in your test class
return _reportCopy;
}
}
Однако это приводит к следующей проблеме: -
ISessionData session = SessionData.Object
Report report = new Report();
session.Report = report;
_report.ShouldEqual(report); // Passes
session.Report.ShouldEqual(report); //Fails!
По существу метод "get" в свойстве по-прежнему возвращает ссылку на исходный объект, на который указывал _report, поскольку ссылка была передана по значению методу SetupGet.
Поэтому нам необходимо обновить значение, возвращаемое получателем отчета, каждый раз, когда вызывается сеттер, который ведет к вашему исходному коду
SessionData
.SetupSet(s => s.TheReport = It.IsAny<Report>())
.Callback<RDLDesigner.Common.Report>(r => {
_sessionReport = r;
SessionData.SetupGet(s => s.TheReport).Returns(_sessionReport);
});
Это гарантирует, что значение, возвращаемое методом Get, всегда синхронизируется с предыдущим вызовом метода set. И приводит к чему-то, что (функционально) ведет себя как: -
public Report Report {
set {
// Sets the field on the test class
_reportCopy = value;
}
get {
// Copy of the value of the _report reference field in your test class
return _reportCopy;
}
}