Причина, по которой обратный вызов используется в вызове 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;
}
}