Próbuję sfałszować wywołanie zindeksowanej właściwości. Tj. Chciałbym zadać następujące pytania:
object result = myDictionaryCollection["SomeKeyValue"];
a także wartość ustawiającą
myDictionaryCollection["SomeKeyValue"] = myNewValue;
Robię to, ponieważ muszę kpić z funkcjonalności klasy, której używa moja aplikacja.
Czy ktoś wie, jak to zrobić z MOQ? Wypróbowałem różne warianty:
Dictionary<string, object> MyContainer = new Dictionary<string, object>();
mock.ExpectGet<object>( p => p[It.IsAny<string>()]).Returns(MyContainer[(string s)]);
Ale to się nie kompiluje.
Czy to, co próbuję osiągnąć, jest możliwe dzięki MOQ, czy ktoś ma jakieś przykłady, jak mogę to zrobić?
Odpowiedzi:
Nie jest jasne, co próbujesz zrobić, ponieważ nie pokazujesz deklaracji kpiny. Próbujesz kpić ze słownika?
MyContainer[(string s)]
nie jest prawidłowy w C #.To kompiluje:
var mock = new Mock<IDictionary>(); mock.SetupGet( p => p[It.IsAny<string>()]).Returns("foo");
źródło
SetupSet
zamiastExpectGet
. działa również dla seterów.Ash, jeśli chcesz mieć makietę sesji HTTP, to ten fragment kodu załatwia sprawę:
/// <summary> /// HTTP session mockup. /// </summary> internal sealed class HttpSessionMock : HttpSessionStateBase { private readonly Dictionary<string, object> objects = new Dictionary<string, object>(); public override object this[string name] { get { return (objects.ContainsKey(name)) ? objects[name] : null; } set { objects[name] = value; } } } /// <summary> /// Base class for all controller tests. /// </summary> public class ControllerTestSuiteBase : TestSuiteBase { private readonly HttpSessionMock sessionMock = new HttpSessionMock(); protected readonly Mock<HttpContextBase> Context = new Mock<HttpContextBase>(); protected readonly Mock<HttpSessionStateBase> Session = new Mock<HttpSessionStateBase>(); public ControllerTestSuiteBase() : base() { Context.Expect(ctx => ctx.Session).Returns(sessionMock); } }
źródło
TestSuiteBase
biblioteka czy twoja własna klasa?Jak poprawnie zauważyłeś, istnieją różne metody
SetupGet
iSetupSet
odpowiednio inicjalizujące metody pobierające i ustawiające. ChociażSetupGet
jest przeznaczony do użytku dla właściwości, a nie indeksatorów, i nie pozwoli na obsługę przekazanego klucza. Aby być precyzyjnym, dla indeksatorówSetupGet
iSetup
tak zadzwoni :internal static MethodCallReturn<T, TProperty> SetupGet<T, TProperty>(Mock<T> mock, Expression<Func<T, TProperty>> expression, Condition condition) where T : class { return PexProtector.Invoke<MethodCallReturn<T, TProperty>>((Func<MethodCallReturn<T, TProperty>>) (() => { if (ExpressionExtensions.IsPropertyIndexer((LambdaExpression) expression)) return Mock.Setup<T, TProperty>(mock, expression, condition); ... } ... }
Aby odpowiedzieć na Twoje pytanie, oto przykładowy kod wykorzystujący podstawy
Dictionary
do przechowywania wartości:var dictionary = new Dictionary<string, object>(); var applicationSettingsBaseMock = new Mock<SettingsBase>(); applicationSettingsBaseMock .Setup(sb => sb[It.IsAny<string>()]) .Returns((string key) => dictionary[key]); applicationSettingsBaseMock .SetupSet(sb => sb["Expected Key"] = It.IsAny<object>()) .Callback((string key, object value) => dictionary[key] = value);
Jak widać, musisz jawnie określić klucz, aby skonfigurować program ustawiający indeksator. Szczegóły opisano w innym pytaniu SO: Moq indeksowana właściwość i użyj wartości indeksu w funkcji return / callback
źródło
Nie jest to takie trudne, ale trochę zajęło znalezienie tego :)
var request = new Moq.Mock<HttpRequestBase>(); request.SetupGet(r => r["foo"]).Returns("bar");
źródło
Wygląda na to, że to, co próbowałem zrobić z MOQ, nie jest możliwe.
Zasadniczo próbowałem MOQ obiekt typu HTTPSession, w którym klucz elementu ustawianego na indeks można było określić tylko w czasie wykonywania. Dostęp do właściwości indeksowanej potrzebny do zwrócenia wartości, która została wcześniej ustawiona. Działa to w przypadku indeksów opartych na liczbach całkowitych, ale indeksy oparte na ciągach znaków nie działają.
źródło