2017-01-20 8 views
0

Вопрос довольно прост. У меня Moq'ed IDocumentClient (который является основным клиентом DocumentDB .NET). Я Moq'ing метод ExecuteStoredProcedureAsync(). Он возвращает тип StoredProcedureResponse (конкретный тип), но его интерфейс сильно заблокирован.Как издеваться над StoredProcedureResponse

Я понял, что могу просто создать StoredProcedureResponse и вставить свою полезную нагрузку в свойство Response, но это setter является приватным. Более того, единственный конструктор без параметров.

Что мне здесь не хватает? Было бы идеально, если бы метод возвращал тип интерфейса (IStoredProcedureResponse), но у меня нет контроля над этим. Я понимаю, что могу написать обертку вокруг IDocumentClient, но это невозможно.

Единственное, что я могу придумать, это расширить и принудительно переопределить свойство с помощью «нового» ключевого слова - НО, в действительном кодовом коде у меня был бы ужасный взлом, в котором я проверяю тип времени выполнения и понижающе для использования переопределения Ресурс Недвижимость.

+0

Что вы пытаетесь проверить? Вы не упомянули об этом в своем вопросе. – CodingYoshi

+0

Я тестирую код, который вызывает метод IDocumentClient.ExecuteStoredProcedureAsync(). Следовательно, я пытаюсь высмеять ответ этого метода, который является конкретным типом, о котором я упоминал выше. – Jmoney38

+0

Я высмеиваю на уровне JavaScript, используя node.js, поэтому я не пытался делать то, что вы есть, но можете ли вы просто сделать то, что вам нужно, в свойстве «StoredProcedureResponse.Response»? –

ответ

1

Требуется ли интерфейс IDocumentClient на вашем верхнем уровне? Если нет, то вы можете создать интерфейс сервиса:

public interface IDocumentService 
{ 
    Task<IStoredProcedureResponse<T>> ExecuteStoredProcedureAsync<T>(string query, IEnumerable<object> parameters); 
} 

В этом случае, или один аналогичный, вы могли бы реализовать прямую службу, которая использует DocumentClient и макет службы, которая просто возвращает высмеивал IStoredProcedureResponse.

Кстати, мне кажется странным, что IDocumentClient.ExecuteStoredProcedureAsync возвращает конкретный экземпляр, который ТАКЖЕ наследуется от интерфейса.

+0

Вы совершенно правы, но я действительно хочу избежать разрыва существующего кода, который у нас есть, который говорит напрямую с интерфейсом IDocumentClient. – Jmoney38

+0

Если вы связаны как таковые, вы можете продолжить свою стратегию inherit/new, или вы можете использовать экземпляр StoredProcedureResponse по умолчанию и использовать выражение, основанное на выражении, для обновления значений свойств. – Eric

0

Использование отражения для его создания:

Type type=typeof(StoredProcedureResponse); 
var spr = (StoredProcedureResponse)Activator.CreateInstance(type,true); 

и установить свойства и все остальное, вам нужно с помощью отражения, а также:

spr.GetType().InvokeMember("PropertyName", 
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty, 
Type.DefaultBinder, obj, "MyName"); 
+0

Я пробовал это, но отражение не позволяет мне установить свойство, потому что нет сеттера на самом деле. Следовательно, я думаю, что они переопределяют геттер для выполнения реальной логики для получения возвращаемого значения. Следовательно, я пытаюсь перестроить класс, чтобы каким-то образом понять, что мне нужно, чтобы установить конфиденциально через отражение. – Jmoney38

+0

Вы взломали сборку с помощью Reflector и т. Д.? – Eric

+0

А также приведенный выше код запрашивает публичный сеттер. Существует также BindingFlags.NonPublic. – Eric

0

Читая комментарии, я нашел простое решение:

var response = new StoredProcedureResponse<T>(); 
response.GetType().InvokeMember("responseBody", 
       BindingFlags.Instance | BindingFlags.SetField | BindingFlags.NonPublic, Type.DefaultBinder, response, new object[] {new T()}); 
Смежные вопросы