2015-12-03 5 views
5

、私は時々、正しく、彼らがテストするためのものの事をテストするために構成されていなかったが、問題があるため、デフォルト(ルース)モックの挙動を発見されなかったテストを見つける:AutoMoqCustomizationでStrict MockBehaviorを使用するにはどうすればよいですか? AutoFixture.AutoMoqパッケージにAutoFixtureを使用して

public interface IService 
{ 
    bool IsSomethingTrue(int id); 
} 

void Main() 
{ 
    var fixture = new Fixture() 
     .Customize(new AutoMoqCustomization()); 
    var service = fixture.Freeze<Mock<IService>>(); 
    Console.WriteLine(service.Object.IsSomethingTrue(1)); // false 
} 

MockをStrictの動作で作成させたいので、私たちは呼び出す予定のメソッドに対してSetup()を呼び出す必要があります。私はこのような個々のモックのためにこれを行うことができます。

fixture.Customize<Mock<IService>>(c => c.FromFactory(() => new Mock<IService>(MockBehavior.Strict))); 

しかしAutoMoqCustomizationのソースコード(経由コーミング後)と、様々なISpecimenBuilderと他の実装、私はかなりちょうどすべてを作るための最善の方法へと迷ってしまいましたモックは厳密な動作で初期化されます。フレームワークは非常に柔軟で拡張性が高いと思われるので、これを行う簡単な方法があると確信しています。

答えて

3

このようなことを可能にするシンプルな組み込み機能はありませんが、それはであり、それはやっていけません。

本来、MockConstructorQueryを変更して、MockBehaviorという値をとり、MockBehavior.Strictを渡すコンストラクタを呼び出すようにする必要があります。

さて、あなたができない変更MockConstructorQueryでその行動が、あなたは出発物質としてMockConstructorQueryを使用してIMethodQueryを実装する新しいクラスを作成することができるはずですので、そのクラスは、コードの一部だけ9-10行ですポイント。

同様に、あなたはまた、厳格なモックの構成の代わりに、MockConstructorQueryでカスタムIMethodQueryを使用していることを唯一の例外を除いて、ほぼ正確AutoMoqCustomizationと同じことカスタムICustomizationを作成する必要があります。それはあなたが書く必要がある別の7行のコードです。

私の経験では、厳しいモックを使用していることはすべて、悪い考えですです。それはあなたのテストを脆くするでしょう、そして、あなたは '壊れた'テストを修復するために多くの時間を無駄にします。私はあなたがこれをしないことを推奨することができますが、今私はあなたに警告しました。それはあなたの足です。

+0

感謝。私はそれを動作させることができるかどうかがわかります。厳格なモックについて:モックが本当に「モック」だった場合、あなたのポイントは有効だと思います。残念なことに、私のモックのほとんどは実際に値を返すと予想される*スタブ*の目的に役立ちます。 SUTがスタブから返されたデータに依存していて、スタブを設定していない場合、最良の場合はテストが失敗し、最悪の場合はテストが間違った理由で失敗します。どちらの場合でも、NREがどこから来ているのかを推測するのではなく、どのスタブが設定する必要があるかを示すコード行をすぐに見ることができます。 – StriplingWarrior

+0

@StriplingWarrior http://blog.ploeh.dk/2013/10/23/mocks-for-commands-stubs-for-queries –

+0

私はこの記事の例題がかなり工夫されていることを発見しました.CQSを作成してユーザーオブジェクトを作成して返しますGetUserメソッドに提供されたIDさえも持っていません。それらは、私が典型的にはメソッドに対して行われる変更の種類ではありません。私が定期的に見ている変更は、たとえその記事の最後の正しい例のように書かれていても、単体テストの変更を必要とします。それが起こると、Strict mockのフェイル・ファースト動作は時間を大幅に節約し、さらに重要なことに、私の単体テストがテストしているものをテストしていることを保証するのに役立ちます。 – StriplingWarrior

0

興味のある方には、@ MarkSeemannの返信がコードに翻訳されています。私はそれがすべてのユースケースをカバーしていないと確信しており、それは重くテストされていませんでした。しかし、それは良い出発点でなければなりません。フィードバックのための

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 
using Moq; 
using Ploeh.AutoFixture; 
using Ploeh.AutoFixture.AutoMoq; 
using Ploeh.AutoFixture.Kernel; 

namespace ConsoleApplication1 
{ 
    public class StrictAutoMoqCustomization : ICustomization 
    { 
     public StrictAutoMoqCustomization() : this(new MockRelay()) { } 

     public StrictAutoMoqCustomization(ISpecimenBuilder relay) 
     { 
      // TODO Null check params 
      Relay = relay; 
     } 

     public ISpecimenBuilder Relay { get; } 

     public void Customize(IFixture fixture) 
     { 
      // TODO Null check params 
      fixture.Customizations.Add(new MockPostprocessor(new MethodInvoker(new StrictMockConstructorQuery()))); 
      fixture.ResidueCollectors.Add(Relay); 
     } 
    } 

    public class StrictMockConstructorMethod : IMethod 
    { 
     private readonly ConstructorInfo ctor; 
     private readonly ParameterInfo[] paramInfos; 

     public StrictMockConstructorMethod(ConstructorInfo ctor, ParameterInfo[] paramInfos) 
     { 
      // TODO Null check params 
      this.ctor = ctor; 
      this.paramInfos = paramInfos; 
     } 

     public IEnumerable<ParameterInfo> Parameters => paramInfos; 

     public object Invoke(IEnumerable<object> parameters) => ctor.Invoke(parameters?.ToArray() ?? new object[] { }); 
    } 

    public class StrictMockConstructorQuery : IMethodQuery 
    { 
     public IEnumerable<IMethod> SelectMethods(Type type) 
     { 
      if (!IsMock(type)) 
      { 
       return Enumerable.Empty<IMethod>(); 
      } 

      if (!GetMockedType(type).IsInterface && !IsDelegate(type)) 
      { 
       return Enumerable.Empty<IMethod>(); 
      } 

      var ctor = type.GetConstructor(new[] { typeof(MockBehavior) }); 

      return new IMethod[] 
      { 
       new StrictMockConstructorMethod(ctor, ctor.GetParameters()) 
      }; 
     } 

     private static bool IsMock(Type type) 
     { 
      return type != null && type.IsGenericType && typeof(Mock<>).IsAssignableFrom(type.GetGenericTypeDefinition()) && !GetMockedType(type).IsGenericParameter; 
     } 

     private static Type GetMockedType(Type type) 
     { 
      return type.GetGenericArguments().Single(); 
     } 

     internal static bool IsDelegate(Type type) 
     { 
      return typeof(MulticastDelegate).IsAssignableFrom(type.BaseType); 
     } 
    } 
} 

使用

var fixture = new Fixture().Customize(new StrictAutoMoqCustomization()); 
関連する問題