1

私は WCF に関しては経験が浅く、WCF サービスを簡単にモックする方法を本当に理解できません。

状況: クライアントとサーバーの両方が、サービスを定義するインターフェイスにアクセスできます。たとえば、次のようになります。

public interface ICustomerService
{
  [OperationContract]
  Customer GetCustomer(int id);
}

さて、私の最初の質問は、共有ライブラリでサービスを定義する同じインターフェイス タイプをクライアントとサーバーで共有したくない理由があるかどうかです。もちろん、サービスのコンシューマが .NET でない場合や、ライブラリを持たないサード パーティにサービスを公開する場合は、その可能性はまったくありませんが、可能性がある場合にそれを共有してもそれらを傷つけることはありません。他のシナリオですよね?

次に、それが悪い考えではない場合、実際に Visual Studio にサービス インターフェイスを再利用させるにはどうすればよいでしょうか? 共有アセンブリでも定義されている をCustomerチェックすることで、型を共有することができましたが、それでもインターフェイスが再生成されます。Re-use types

しかし、これらの問題に関係なく、クライアントをモック可能にするにはどうすればよいでしょうか? VS で生成されたサービス参照を調べると、具体的な型が得られますが、コードでその型を直接参照したくないので、インターフェイスと対話したいと考えています。生成されたクライアントを として公開するとICustomerService、これCloseは機能しますが、インターフェイスでメソッドが定義されていないため、メソッドがありません。

私はまた、次のアプローチを考え、自動生成クライアントを完全に放棄し、クライアントを自分で書くだけです。

public interface IServiceClient<T>
{
    void Close();
    T Services { get; }
}

public class CustomerServiceClient : ClientBase<ICustomerService>, ICustomerService, IServiceClient<ICustomerService>
{
    public Customer GetCustomer(int id)
    {
        return base.Channel.GetCustomer(id);
    }

    public ICustomerService Services
    {
        get { return this; }
    }
}

それは機能IServiceClient<ICustomerService>し、IoC コンテナーとして公開することができますが、それが今であり、インターフェイスが変更さclient.Services.GetCustomer(1)れたときにクライアントを簡単に再生成するという利点を失ったことに注意してください。ICustomerService追加するのは簡単なコードですが、これを維持するのは面倒かもしれません。

別の可能性は、生成されたクラスが であるという事実を利用することですpartial。これを行うときにも機能します。

interface ICloseable
{
  void Close();
}

interface ClientInterface : ICustomerService, ICloseable
{
}

partial class CustomerServiceClient : IClientInterface
{

}

しかし、それは偽のクラスとインターフェイスを作成しました。これは災害ではありませんが、あまりきれいではありません。

いずれかのルートに進む前に、見落としている明らかなものはありますか?

4

4 に答える 4

2

Ninject.Extension.Wcf を試しましたか? WCF サービスを注入する方法の例があり、それらを閉じる方法も示しています。

https://github.com/ninject/ninject.extensions.wcf

http://teamcity.codebetter.com/project.html?projectId=project3&tab=projectOverview

于 2010-11-03T14:00:27.487 に答える
0

いいえ、単一のアセンブリでインターフェイスを共有しても、管理されていないクライアントの可能性が損なわれることはありません。心配しないでください。

取るべき別のルートについては、モックフレームワークを使用したことはありませんが、それらのいずれかが役立つかどうか疑問に思います。とはいえ、テストのニーズを「単体テスト」から「統合テスト」に昇格することを検討したことはありますか? 私が WCF サービスをテストしてきた方法は、実際の WCF クライアント スタブを使用して偽のクライアントを作成することです。これにより、実際のサーバーが使用され、実際のサーバーは偽のサーバー コントローラーと通信します。次に、 appdomain magicを使用して、クライアント プロセスとサーバー プロセスの両方を 1 つのプロセスで実行します。その単一のプロセスは、Visual Studio の単体テスト フレームワークのコンテキストで実行されます。そのため、単体テストであるかのように統合テストを実行しています。非常に素晴らしい!

于 2010-11-01T17:55:34.057 に答える
0

通常、自動生成クライアントは、クライアントとサーバー間でコードを共有できないシナリオでのみ役立ちます。それあなたのために新しいタイプを生成します。

コントラクト (つまり、インターフェイスとそれが使用する DataContract 型) を共有する正しい方法は、サーバーとクライアントの両方に配布する必要がある別のアセンブリでこれらの型を定義することです。次に、サーバー上でサーバー実装を作成し、クライアント上でクライアント実装を作成できます。

すぐに利用できる型があれば、独自のクライアント実装を簡単に作成できます。これは通常、私が行うことです。これにより、サービス実装のモックや注入も簡単になります。

クライアントとサーバー間でコントラクト アセンブリを共有するオプションがない場合、次善の策は、部分的に生成されたクラスを利用して、インターフェイスと Close メソッドを追加することです。

于 2010-11-01T17:56:22.980 に答える
0

Windsor を IoC として使用している場合 (Unity については不明)、WCF クライアントを挿入することができます。つまり、消費するコードは ICustomerService だけを気にする必要があります。

container = new WindsorContainer().AddFacility<WcfFacility>();

container.Register(Component
  .For<ICustomerService>()
  .ActAs(DefaultClientModel
  .On(WcfEndpoint.FromConfiguration("CustomerService")))
  .LifeStyle.Transient);
于 2010-11-01T17:52:25.113 に答える