인덱스 속성을 MOQ하는 방법


82

인덱싱 된 속성에 대한 호출을 모의하려고합니다. 즉, 다음을 moq하고 싶습니다.

object result = myDictionaryCollection["SomeKeyValue"];

또한 setter 값

myDictionaryCollection["SomeKeyValue"] = myNewValue;

내 앱에서 사용하는 클래스의 기능을 모의해야하기 때문에이 작업을 수행합니다.

누구든지 MOQ로 이것을 수행하는 방법을 알고 있습니까? 다음과 같은 변형을 시도했습니다.

Dictionary<string, object> MyContainer = new Dictionary<string, object>();
mock.ExpectGet<object>( p => p[It.IsAny<string>()]).Returns(MyContainer[(string s)]);

그러나 그것은 컴파일되지 않습니다.

내가 MOQ로 달성하려는 것이 가능합니까? 누군가 내가 어떻게 할 수 있는지에 대한 예가 있습니까?


스텁 객체를 사용하는 것이 더 쉬울까요? 필요한 값을 설정하고 필요한 인덱스를 확인하십시오.
Søren Spelling Lund

답변:


96

모의 선언문을 보여주지 않기 때문에 무엇을 하려는지 명확하지 않습니다. 사전을 조롱하려고합니까?

MyContainer[(string s)] 유효한 C #이 아닙니다.

이것은 다음을 컴파일합니다.

var mock = new Mock<IDictionary>();
mock.SetupGet( p => p[It.IsAny<string>()]).Returns("foo");

1
이것도 작동합니다. 새 구문 SetupSetExpectGet. 세터에서도 작동합니다.
tmont 2010

1
IDictionary은은 System.Collections에서하지 System.Collections.Generic에서입니다
upInCloud

20

Ash, HTTP 세션 모의를 사용하려면 다음 코드가 작업을 수행합니다.

/// <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);
    }
}

멋진 한 -이 내가 +1 필요한 그냥 뭐이었다
이안 옥 슬리

1
이 코드의 어떤 부분이 테스트중인 코드가 모의 세션을 사용하게하나요? 가 TestSuiteBase도서관이나 자신의 클래스는?
StuperUser

1
그것은 모의가 아니라 가짜입니다. 그냥 말해.
Chris Peacock

17

제대로 발견으로이 뚜렷한 방법이 있습니다 SetupGetSetupSet각각 getter 및 setter를 초기화 할 수 있습니다. 하지만이 SetupGet속성이 아니라 인덱서를 사용하기위한 것입니다, 당신이 그것을 전달 키를 처리 할 수 없습니다. 정확하게 말하면 인덱서의 SetupGet경우 Setup어쨌든 다음 을 호출 합니다.

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);
    ...
  }
  ...
}

질문에 답하기 위해 다음은 기본 Dictionary값을 저장 하는 데 사용하는 코드 샘플입니다 .

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);

보시다시피 인덱서 setter를 설정하려면 명시 적으로 키를 지정해야합니다. 자세한 내용은 다른 SO 질문에 설명되어 있습니다. Moq 인덱싱 된 속성 및 반환 / 콜백에서 인덱스 값 사용


1
이것이 제가 찾고 있던 것입니다 !! 다른 예 아무도 일하지
피오나 - myaccessible.website

8

그다지 어렵지는 않지만 그것을 찾는 데 조금 걸렸습니다. :)

var request = new Moq.Mock<HttpRequestBase>();
request.SetupGet(r => r["foo"]).Returns("bar");

-4

내가 MOQ로하려는 것이 불가능한 것 같습니다.

본질적으로 저는 HTTPSession 유형 객체를 MOQ하려고 시도했습니다. 여기서 인덱스로 설정되는 항목의 키는 런타임에만 확인할 수 있습니다. 이전에 설정된 값을 반환하는 데 필요한 인덱싱 된 속성에 대한 액세스. 이것은 정수 기반 인덱스에 대해 작동하지만 문자열 기반 인덱스는 작동하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.