問題
私は、他の多くのサービスを利用するかなり大きなアプリケーションを持っています。テスト シナリオでは、単体テストをサード パーティのシステムに依存させたくないので、サービスをフェイクやモックなどに置き換えたいと考えています。
私はすでにほとんどの大変な作業を行っており、具体的なサービスをIService
. 具体的な Service は DI フレームワークに接続されています
今、それらをランダムに生成された偽物に置き換えたいと思います。
コード
サンプルサービスのインターフェース:
public interface ISimpleService
{
int Fizz(int input);
string Buzz(string input);
}
サンプル サービス ファクトリのインターフェイス:
public interface ISimpleServiceFactory
{
ISimpleService Create();
}
可能な限りシンプルな実装
public static void Main(string[] args)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var service = fixture.Create<ISimpleService>();
var fizzResult = service.Fizz(42);
var buzzResult = service.Buzz("I'd like something random...");
}
これは私が基本的に欲しいものを示しています。インターフェイスで指定されたタイプのランダムなものを返すメソッドを使用して、自動フィクスチャに動的プロキシオブジェクトを作成してもらいたいだけです...
ここでは AutoMoq を使用していることに注意してください。デフォルトでは、Fixture はインターフェイスからオブジェクトを作成したくないためですが、他のフレームワークも試しました: FakeItEasy、AutoRhinoMock
回避策
すべてを手動で設定することで機能する実装
public static void Main(string[] args)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var serviceMock = fixture.Create<Mock<ISimpleService>>();
// These two lines below cause the magic now
serviceMock.Setup(x => x.Fizz(It.IsAny<int>())).Returns(fixture.Create<int>());
serviceMock.Setup(x => x.Buzz(It.IsAny<string>())).Returns(fixture.Create<string>());
var service = serviceMock.Object;
var fizzResult = service.Fizz(42);
var buzzResult = service.Buzz("I'd like something random...");
}
これにより、目的の結果が得られます: ランダムな int を持つ fizzResult、ランダムな文字列 (デフォルトでは GUID) を持つ budsResult です。 .. (それらは外部の SOAP サービスなどであり、それを助けることはできません) すべてを手動で設定したくありません。一般的な解決策があれば、それは素晴らしいことです...
すべてを手動で設定することで機能するファクトリの実装
お気づきかもしれませんが、ISimpleServiceFactory
インターフェイスも投稿しました。実際のコンクリートには多くの構成が必要なため、これは実際の状況に似ていISimpleService
ます。したがって、この種の実用的なソリューションを使用すると、次のようになります。
public static void Main(string[] args)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var serviceFactoryMock = fixture.Create<Mock<ISimpleServiceFactory>>();
var serviceMockDelegate = new Func<ISimpleService>(() =>
{
var serviceMock = fixture.Create<Mock<ISimpleService>>();
serviceMock.Setup(x => x.Fizz(It.IsAny<int>())).Returns(fixture.Create<int>());
serviceMock.Setup(x => x.Buzz(It.IsAny<string>())).Returns(fixture.Create<string>());
return serviceMock.Object;
});
serviceFactoryMock.Setup(x => x.Create()).Returns(serviceMockDelegate);
var service = serviceFactoryMock.Object.Create();
var fizzResult = service.Fizz(42);
var buzzResult = service.Buzz("I'd like something random...");
}
これは少し混乱しているようで、これはかなり小さなインターフェースです。実際のサービスは何百ものメソッドを含む、何層もの深さがあります。
特定の条件を必要とするコード内のメソッドについては、明らかにこれらの条件を手動で設定しますが、それ以外はすべてデフォルトでランダム値にする必要があります。ランダムなオブジェクトを大量に生成すると、ファジー テストも少し可能になります。
この手動設定をすべて行わずに、ランダム オブジェクトを自動的に生成する方法はありますか?