Введение в тестирование WCF

ОГЛАВЛЕНИЕ

Являетесь ли вы новичком в среде Windows Communication Foundation (WCF), или уже немного работали с ней, существуют некоторые методики и принципы тестирования, которые облегчат вашу работу с WCF. Существует несколько способов осмысления WCF — я склоняюсь к тому, что службы WCF являются имеющим большое значение расширением веб-служб. Подобно веб-службам, службы WCF позволяют создавать распределенные системы с помощью ориентированной на службы архитектуры. Однако службы WCF предоставляют гораздо большую гибкость (например, выбор транспортного протокола) и дополнительный набор компонентов (например, операции и безопасность). WCF — это гораздо больше, чем просто расширение веб-служб, но если вы мало знакомы с WCF, изначально имеет смысл рассматривать их именно как такое расширение.

На рис. 1 показана простая, но вполне представительная ситуация с WCF. Здесь Internet Explorer® выступает в качестве клиентской программы и получает доступ к веб-приложению ASP.NET, которое принимает некоторый текст от пользователя и вычисляет для него криптографический хэш. Для фактического выполнения расчетов для хэширования веб-приложение ASP.NET вызывает «за кадром» службу WCF. В этом конкретном случае служба WCF размещается посредством IIS и используется веб-приложением ASP.NET, но, как я вскоре объясню, помимо варианта с IIS, службы WCF можно размещать несколькими способами, и они могут быть использованы приложением или службой практически любого типа.

 

Рис. 1 Типичный случай использования WCF

Самый простой тип тестирования службы WCF включает проверку правильности работы функций операций службы. Один из возможных подходов заключается в тестировании службы WCF вручную с помощью пользовательского интерфейса приложения. Но, хотя тестирование вручную является необходимым, использование этого подхода для тестирования основных функций службы WCF требует много времени, приводит к ошибкам, является неэффективным и попросту нудным.

Более приемлемый подход заключается в создании программы автоматизации тестирования, подобной той, этап выполнения которой показан на рис. 2. На снимке экрана показана написанная мной программа тестирования консольного приложения. Она подает входной текст непосредственно внутренней службе WCF, получает от службы сообщение с ответом и определяет результат конкретного тестирования — успешное завершение или сбой. Схема на рис. 3 является упрощенным представлением и сводкой взаимосвязей между программами, приведенными на рис. 1 и 2. Во многих случаях службы WCF извлекают информацию из внутренней базы данных или получают информацию от веб-служб или служб WCF, но эти ситуации не включены в рис. 3.

 

Рис. 2 Тестирование службы WCF

Рис. 3 Упрощенные взаимосвязи

Затем будет рассмотрена серверная служба WCF, чтобы было совершенно понятно, что именно тестируется. Будет вкратце обсуждено использующее службу WCF веб-приложение ASP.NET, показанное на рис. 1, и будет подробно описана программа тестирования. В заключение будут затронуты некоторые другие случаи тестирования WCF.

Тестируемая система

Тестируемая система состоит из серверной службы WCF и веб-приложения ASP.NET, которое использует службу WCF. Службы WCF обладают выдающейся гибкостью. Одним из важнейших решений при создании службы WCF является выбор для службы механизма размещения. Существует четыре основных варианта: использование IIS, использование Windows® Service, размещение на собственном сервере и использование WAS (Windows Activation Service — служба активирования Windows). Возможно, вы знакомы с использованием IIS и Windows. Размещение на собственном сервере влечет размещение WCF в программе, управляемой Microsoft® .NET Framework, например, консольном приложении. WAS представляет собой новый механизм активирования процесса, имеющийся в Windows Server® 2008 и Windows Vista®. У каждого варианта размещения WCF имеются достоинства и недостатки, зависящие от конкретного случая разработки. В этой статье для примера службы WCF я решил использовать IIS. Такой выбор позволяет использовать преимущества IIS, например встроенные интегрированные управление и текущий контроль, перезапуск процесса, завершение работы при ожидании и активирование на основе сообщений.

Создание службы WCF, размещаемой посредством IIS, является поразительно легкой задачей. Я начинаю с запуска Visual Studio® 2008 в среде Windows Server 2003. Отмечу, что если вы решите разрабатывать службу WCF на машине, работающей под управлением Windows Server 2008 или Windows Vista, в процессе разработки придется иметь дело с проблемами, связанными с их расширенными фукнциями безопасности. Однако объем данной статьи не позволяет их описать.

Далее в меню Visual Studio я выбираю режим «Файл | Создать | Веб-узел». Затем в диалоговом окне создания веб-узла я выбираю шаблон службы WCF (установленный по умолчанию в Visual Studio 2008) и целевую среду .NET Framework 3.5. Для поля Location (Местонахождение) выбираю значение HTTP и указываю localhost/WCF/CryptoHashService. При таком подходе на моей рабочей машине создается полное веб-приложение и виртуальный каталог IIS в папке C:\Inetpub\wwwroot\WCF\CryptoHashService; вместо этого можно было бы выбрать местонахождение в файловой системы моей машины и использовать встроенный в Visual Studio сервер разработки веб-приложений.

Я принял решение использовать в качестве языка реализации C#; однако службы WCF можно реализовать также с помощью Visual Basic® .NET. После того, как в диалоговом окне нажата кнопка «OK», Visual Studio создает полнофункциональную службу WCF с двумя примерами операций, названными GetData и GetData­UsingDataContract. Взглянув на окно обозревателя решений, вы увидите, что Visual Studio генерируре четыре важных файла: IService.cs, Service.cs, Service.svc и web.config. Файл IService.cs содержит определения интерфейса для операций WCF, а файл Service.cs содержит фактические реализации ваших операций. В данном случае я принял решение переименовать эти два файла в ICryptoHashService.cs и CryptoHashService.cs соответственно. Далее я загружаю ICryptoHashService.cs в редактор кода Visual Studio, удаляю код примера интерфейса и заменяю его следующим кодом.

[ServiceContract]
public interface ICryptoHashService
{
   [OperationContract]
   string GetCryptoHash(string s);
}

Здесь только одна операция, GetCryptoHash, но можно было бы добавить и другие. Обратите внимание на то, что большую часть фактической работы по генерации кода вместо меня выполняют «за кадром» атрибуты [SeviceContract] и [OperationContract]. Далее я редактирую файл реализации CryptoHashService.cs, добавляя ссылку оператора using на пространство имен System.Security.Cryptography, и пишу следующий код.

public class CryptoHashService : ICryptoHashService
{
   public string GetCryptoHash(string s)
   {
     byte[] ba = Encoding.Unicode.GetBytes(s);
     MD5CryptoServiceProvider sp = new MD5CryptoServiceProvider();
     byte[] hash = sp.ComputeHash(ba);
     string result = BitConverter.ToString(hash);
     return result;
   }
}

Сначала я изменяю имя моего класса CryptoHashService и класса, от которого он произведен, чтобы они соответствовали имени, используемому в моем определении интерфейса. В моем методе GetCryptoHash я просто использую метод GetBytes для преобразования входного аргумента в массив байт, получаю экземпляр класса MD5CryptoServiceProvider и использую метод ComputeHash для преобразования массива байтов в 16-байтовый крипотграфический хэш MD5. Результирующий хэш преобразую из массива байт в понятную строку с помощью статического метода BitConverter.ToString, затем возвращаю эту строку. Чтобы не удлинять пример, я опустил обычную проверку ошибок, которую следует использовать в рабочей среде, например проверку входного аргумента, перехват исключений и т.д.. Далее я редактирую файл Service.svc, чтобы отразить изменения в именах, заменяя «Service» на «CryptoHashService».

<%@ ServiceHost Language="C#" Debug="true" Service="CryptoHashService"
      CodeBehind="~/App_Code/CryptoHashService.cs" %>

Редактирование имен завершается обновлением двух ссылок на имена в файле web.config.

<system.serviceModel>
     <services>
     <service name="CryptoHashService" behaviorConfiguration="Servic Behavior">
   <!-- Service Endpoints -->
   <endpoint address=""binding="wsHttpBinding" contract="ICryptoHashService">

Обратите внимание на запись binding="wsHttpBinding". Привязка WCF представляет собой коллекцию данных, указывающих на то, каким образом служба WCF осуществляет связь с клиентами, включая транспортный протокол, используемый службой, используемую схему кодировки текста и т.д. Можно использовать встроенные привязки или создавать пользовательские привязки. Привязка wsHttpBinding является предварительно настроенной, используемой по умолчанию при создании размещаемой посредством IIS службы WCF. Visual Studio генерирует еще одну часть файла web.config:

<endpoint address="mex" binding="mexHttpBinding"
   contract="IMetadataExchange"/>

Эта запись сообщает моей службе WCF о необходимости предоставлять доступ к метаданным, относящимся собственно к службе, чтобы клиентские программы могли проверять ее для определения способа взаимодействия с ней. Теперь можно с успехом строить службу WCF, выбрав в главном меню пункт «Построить | Построить решение». Можно было бы также воспользоваться клавишей F5, чтобы как построить службу WCF, так и получить рекомендации по созданию клиентской программы. Поскольку размещение моей службы выполняется посредством IIS, мне не требуется запускать службу явным образом; служба WCF будет готова к приему входящих сообщений WCF всегда, когда работает IIS.

Теперь приступим к разбору процедуры создания веб-приложения ASP.NET, показанного на рис. 1. Я запускаю новый экземпляр Visual Studio и выдаю команду «Файл | Создать | Веб-узел». В диалоговом окне создания веб-узла я выбираю шаблон веб-узла ASP.NET и в раскрывающемся списке целевых платформ выбираю .NET Framework 3.5. Я использую Location HTTP и выбираю C# в качестве языка. В поле местонахождения ввожу строку localhost/WCF/UtilitiesAndTools для неявного присвоения имени моему веб-приложению. Можно было бы указать местоположение файловой системы на моей рабочей машине и вместо IIS использовать веб-сервер. Далее я добавляю в мое веб-приложение некоторый минимальный код UI.

Код на рис. 4 представляет собой основной UI, без таких деталей форматирования, как стиль шрифта и теги <hr/>. Точный код UI наряду с кодом, приведенном в этой статье, можно получить из материалов для загрузки, прилагаемых к статье.

Рис. 4 Код UI веб-приложения ASP.NET

<body>
  <form id="form1" runat="server">
    <div>
    <asp:Label runat="server" ID="Label"
     Text="Demo Utilities Featuring WCF Services" />
    <asp:Label runat="server" ID="Label2"
     Text="Enter text here:" />
    <asp:TextBox runat="server" ID="TextBox1"
     Height="100px" Width="320px" />
    <asp:Button runat="server" ID="Button1"
     Text="Get MD5 Crypto-Hash" onclick="Button1_Click"
     Width="150px" />
    <asp:Button runat="server" ID="Button2"
     Text="Get SHA1 Crypto-Hash"
     Width="150px" />
    <asp:Label runat="server" ID="Label3"
    Text="Crypto-Hash of your text (computed by WCF Service) is:" />
    <asp:TextBox runat="server" ID="TextBox2"
     Width="320px" />
    </div>
  </form>
</body> 

В данный момент мое веб-приложение ASP.NET ничего не знает о моей службе WCF; однако технологии WCF и ASP.NET разработаны для беспрепятственной совместной работы. В окне обозревателя решений моего проекта веб-приложения я щелкаю правой кнопкой мыши имя проекта и выбираю «Добавить ссылку на службу». Обратите внимание на то, что это новая возможность, дополняющая старые режимы «Добавить ссылку» (обычно использовался для библиотек DLL и пространств имен .NET) и «Добавить веб-ссылку» (обычно использовался для веб-служб ASP.NET).

В результирующем диалоговом окне «Добавить ссылку на службу» я ввожу строку localhost/WCF/CryptoHashService/Service.svc и нажимаю кнопку «Начать». Инструментальное средство добавления ссылки на службу проверяет указанное местоположение на наличие служб и отображает обнаруженные службы; в данном случае службу CryptoHashService WCF. В диалоговом окне, в поле «Пространство имен» я выбираю простое, но удобное описательное имя по умолчанию, ServiceReference1, затем нажимаю кнопку «OK». Visual Studio генерирует весь код прокси, требуемый моему приложению для связи со службой WCF. В частности, я получаю класс с именем CryptoHashServiceClient (т.е, к имени службы WCF добавлено слово «Client»), который дает возможность устанавливать связь со службой CryptoHashService.

В окне конструктора дважды щелкаю элемент элемент управления Button1 для передачи Visual Studio инструкции относительно необходимости зарегистрировать обработчик событий элемента управления. Затем добавляю этот код в метод Button1_Click.

try  
{
   string s = TextBox1.Text;
   ServiceReference1.CryptoHashServiceClient c = 
    new ServiceReference1.CryptoHasahServiceClient();
   string h = c.GetCryptoHash(s);
   TextBox2.Text = h;
}
catch(Exception ex)
{
   TextBox2.Text = ex.Message;
}

Это даже слишком легко! Извлекаю текст из поля TextBox1, образую экземпляр автоматически сгенерированного класса CryptoHashServiceClient, вызываю метод GetCryptoHash объекта и отображаю результирующий крипотографический хэш MD5 (Message Digest version 5) в поле TextBox2. Пользовательский интерфейс веб-приложения на рис. 1 демонстрирует элемент управления кнопки, осуществляющий вычисление криптографического хэша SHA-1 (Secure Hash Algorithm 1), но я не реализовывал эти функции для имитации разрабатываемой системы. После привязки веб-приложения пользователь может запустить Internet Explorer и отыскать приложение, ввести некоторый текст и получить криптографический хэш MD5 текста, вычисленный серверной службой WCF, как показано на рис. 1.