2012-06-20 2 views
2

TL; Что такое хороший и проверяемый способ реализации зависимости между ViewModels и WCF-сервисами в клиенте MVVM?Как вы введете зависимости клиента wcf в ViewModel и сохраните его для проверки?

Пожалуйста, прочитайте остальную часть вопроса для более подробной информации о проблемах, я столкнулся при попытке сделать это:


Я работаю на SilverLight клиента, который подключается к службе WCF, и я хочу написать единичные тесты для клиента. Итак, я ищу хорошее решение для использования клиентов wcf в моих моделях ViewModels и тестирования этого взаимодействия. Я не нашел два решения до сих пор:

Решение 1: Это на самом деле, как я не реализовали до сих пор:

public class ViewModelExample 
{ 
    public ViewModelExample(IServiceClient client) 
    {  
      client.DoWorkCompleted += .. 
      client.DoWorkAsync(); 
    } 
} 

//This is how the interface looks like 
public interface IServiceClient 
{ 
    event EventHandler<AsyncCompletedEventArgs> DoWorkCompleted; 
    void DoWorkAsync(); 
} 

//I was able to put the interface on the generated clients because they are partial classes, like this: 
public partial class GeneratedServiceClient : IServiceClient 
{ 

} 

Хорошая часть: относительно легко издеваться

Плохая часть: мой клиент службы работает до тех пор, пока мой ViewModel, и когда у меня есть параллельные запросы, я не знаю, какой ответ принадлежит какому запросу.

Решение 2: Вдохновленный этим ответом WCF Service Client Lifetime.

public class ViewModelExample 
{ 
    public ViewModelExample(IServiceFactory factory) 
    { 
     var client = factory.CreateClient(); 
     client.DoWorkCompleted += ... 
     client.DoWorkAsync(); 
    } 
} 

хорошая часть: каждый запрос не находится на другом клиенте, так что никаких больше проблем с соответствием запросов с ответами.

Плохая часть: сложнее проверить. Мне приходилось каждый раз писать mocks как для фабрики, так и для wcf-клиента. Это не то, что я хотел бы сделать, так как я alreay есть 200 тестов ... :(

Так что мой вопрос, как вы, ребята, это сделать? Как ваше ViewModels поговорить с ФОС услуг, где вы впрыскивать зависимость, и как вы проверяете, что взаимодействие? Я чувствую, что я что-то не хватает ..

ответ

1

Попробуйте ввести в свою VM Func<IServiceClient> вместо экземпляра клиента; у вас будет «фабрика на уровне языка», а не создание класса для этого. В методе фабрики вы можете создать экземпляр своего клиента, но вы хотите (каждый доступ мог бы создать новый экземпляр для этого, например).

Недостатком является то, что вы все равно должны коснуться ваших тестов по большей части, но я предполагаю, что это будет меньше работы:

public ViewModelExample(Func<IServiceClient> factoryMethod) 
{ 
    var client = factoryMethod(); 
    client.DoWorkCompleted += ... 
    client.DoWorkAsync(); 
} 
+0

круто, мне это нравится, у меня нет другой фабрики, чтобы насмехаться. – stralsi

0

служба WCF должны иметь это собственные тесты, подтверждающие функциональность самого себя.

вы должны затем издевайтесь над этим сервисом WCF и записывайте единичные тесты в своих потребителях.

К сожалению, это боль и что-то, что мы все должны делать. Будьте прагматичны и делайте это, это спасет вас от укуса в будущем.

+1

благодарит Криса, но это именно то, что я спрашивал, как писать сервисы и как писать для них макеты? Как ты делаешь это? – stralsi

0

Вы используете контейнер IoC случайно? Если бы у вас было, эта проблема была бы полностью смягчена контейнером (вы просто зарегистрируете зависимость IService, которая будет создана как новая по каждому запросу).

Если это не так, то

Я бы написать издевается как для завода и клиента ФОС каждый раз

то, как вы имеете дело с такого рода «проблем ". Стоимость относительно небольшая, вероятно, 2-3 дополнительных строки кода за тест (все, что вам нужно сделать, это установить заводский макет, чтобы вернуть служебный макет, который вам нужен в любом случае).

+0

В настоящее время я не использую контейнер IoC, но, на мой взгляд, это не изменит ситуацию, поскольку зависимость IService находится в конструкторе, и мне понадобится один за звонок. .. но вы дали мне еще одну идею, думаете ли вы, что можно использовать контейнер IoC вместо фабрики? Чтобы разрешить IService перед каждым вызовом? – stralsi

+0

@sssilviu: что заставляет вас думать, что вы не сможете предоставить экземпляр клиента для каждой виртуальной машины? Большинство современных контейнеров позволяют вам значительно управлять реализацией объектов/временем жизни. Всякий раз, когда создается новый экземпляр виртуальной машины (при условии, что он создается через контейнер), он может быть загружен новым экземпляром 'IService', таким образом, контейнер IoC работает точно так же, как фабрика фабрики/функции. Это всего лишь вопрос конфигурации/регистрации. –

+0

В настоящее время у меня есть экземпляры клиента для каждой виртуальной машины. Я нуждаюсь в них за вызов службы. – stralsi