2016-04-14 15 views
2

単体テストに問題があります。 私は、スタンダードのReprositoryとUnitOfWorkパターンを持っています。 は例えば、私は、UnitOfWorkのクラスを持っている:プログラムの魔女の別の部分で使用される使い捨てのメソッドの単体テスト

public class UnitOfWork : IDisposable 
{ 
    private readonly MyDbContext _context; 

    ... repositories 
    private IMyEntityRepository _myEntityRepository; 
    ... 
} 

UnitOfWokは、エンティティといくつかの特別な操作を行います。例えば、方法があり、whitchのUnitOfWorkを使用します。

public IEnumerable<MyClass> MyMethod() 
    { 
    using (_unitOfWork = new UnitOfWork()) 
    { 
     var myEntities= _unitOfWork.MyEntityRepository.Get(); 

     var result = ... some logic to convert myEntities collection to IEnumerable<MyClass> 
     return result; 
    } 
    } 

を私の質問はconsruction using(_unitOfWork = new UnitOfWork)がある場合MyMethodはのためのユニットテストを書く方法でしょうか?その場合、どうやって偽のUnitOfWorkを偽のコンテキストで使用できますか?アドバイスありがとう。あなたはこのようなコンストラクタ・インジェクション経由MyMethodメソッドを含むクラスにUnitOfWorkの工場を注入する必要が

+1

UoWクラス内でコンテキストをインスタンス化せず、代わりに(コンストラクタ)依存関係として提供します。 – spender

答えて

1

クラスをより偽造可能でテスト可能にするには、可能であればUnitOfWorkRepositoriesを抽象化し、ファクトリを使用してそれに依存するクラスに注入することをお勧めします。

public interface IUnitOfWork : IDisposable { 
    ... repositories 
    IMyEntityRepository MyEntityRepository; 
    ... 
} 

そして、あなたのUnitOfWork

public class UnitOfWork : IUnitOfWork {...} 

IUnitOfWorkFactoryそれと

public interface IUnitOfWorkFactory { 
    IUnitOfWork Create(); 
} 

そのインターフェイスから派生し、依存クラスは、この

public class MyDependentClass { 
    private readonly IUnitOfWorkFactory unitOfWorkFactory; 

    public MyDependentClass (IUnitOfWorkFactory unitOfWorkFactory) { 
     this.unitOfWorkFactory = unitOfWorkFactory; 
    } 

    public IEnumerable<MyClass> MyMethod() { 
     using (var _unitOfWork = unitOfWorkFactory.Create()) { 
      var myEntities= _unitOfWork.MyEntityRepository.Get(); 

      var result = ... some logic to convert myEntities collection to IEnumerable<MyClass> 
      return result; 
     } 
    } 
} 
のように見えることができます

UnitOfWorkRepositoriesを模擬/偽装することができ、コンテキストを偽造する必要がなくなりました。

は、次のようにあなたがテストを構築することができます

(私は実証の目的のためにMoqFluentAssertを使用しています)あなたはUOWが実際に

MyMethodを呼び出した後に廃棄されていることを確認/テストしたいとしましょう:

[TestMethod] 
public void UOW_Should_Be_Disposed() { 
    //Assert 
    var fake_entities = Enumerable.Range(1, 10).Select(i => new MyEntity()); 
    var mockRepository = new Mock<IMyEntityRepository>(); 
    mockRepository.Setup(m => m.Get()).Returns(fake_entities); 
    var mockUOW = new Mock<IUnitOfWork>(); 
    mockUOW.Setup(m => m.MyEntityRepository).Returns(mockRepository.Object); 
    var mockFactory = new Mock<IUnitOfWorkFactory>(); 
    mockFactory.Setup(m => m.Create()).Returns(mockUOW.Object); 

    //Act 
    var sut = new MyDependentClass(mockFactory.Object); 
    var output = sut.MyMethod().ToList(); 

    //Assert 
    output.Should().NotBeNull(); 
    output.Should().HaveCount(10); 
    output.Should().ContainItemsAssignableTo<MyClass>(); 
    mockUOW.Verify(m => m.Dispose()); 
} 

上記の説明は、前述のフレームワークを使用して簡単にすべてをテストする方法を示しています。

希望します。

+0

詳細な回答をいただきありがとうございます。 – user3609841

1

public class MyClass 
{ 
    private readonly Func<UnitOfWork> unitOfWorkFactory; 

    public MyClass(Func<UnitOfWork> unitOfWorkFactory) 
    { 
     this.unitOfWorkFactory = unitOfWorkFactory; 
    } 

    public IEnumerable<MyClass> MyMethod() 
    { 
     using (unitOfWork = unitOfWorkFactory()) 
     { 
      //.. 
     } 
    } 
} 

は、私はそれを想定していますので、クラスではなくUnitOfWorkFunc<UnitOfWork>を取ることに注意してくださいMyMethodへの各呼び出しにUnitOfWorkの新しいインスタンスを設定します。あなたのテストでは

、あなたが偽のUnitOfWorkを作成し、あなたがこのようなMyClassインスタンスにそれを渡すことができます:

var sut = new MyClass(() => fakeInstance); 

あなたはまたUnitOfWorkがfakeableであることを確認する必要があります。たとえば、具体的なクラスであるため、関連するメソッドがvirtualであることを確認する必要があります。別のアプローチは、UnitOfWorkが実装するインターフェイスIUnitOfWorkと、MyClassが使用するインターフェイスを持つことです。

関連する問題