2012-04-06 19 views
3

私はフレームワークを使ってモッキングしています。Moq、抽象クラスと仮想プロパティ

abstract DataWorkerクラスに由来するSocialWorkerがあります。

SocialWorkerは、私は次のテストを実行しようとしていますvirtual property

としてRepositoriesのカップルへの参照を持っています

private Place _place; 
private Mock<IRepository<Resources.Data.Place>> _placeRepositoryMock; 
private Mock<SocialWorker> _socialWorkerMock; 

[SetUp] 
public void SetUp() 
{ 
    _place = new Place {Name = "A"}; 

    _socialWorkerMock = new Mock<SocialWorker> {DefaultValue = DefaultValue.Mock}; 

    IRepository<Resources.Data.Place> placeRepository = _socialWorkerMock.Object.PlaceRepository; 

    _placeRepositoryMock = Mock.Get(placeRepository); 

    _placeRepositoryMock.Setup(
     repository => 
     repository.Find(It.IsAny<Expression<Func<Resources.Data.Place, bool>>>(), null, null)) 
     .Returns(new[] {new Resources.Data.Place()}); 
} 

[Test] 
public void AddShouldAddANewPlace() 
{ 
    var placeManager = new PlaceManager(_socialWorkerMock.Object); 

    object placeEntity = placeManager.Add(_place); 

    placeEntity.GetType().Should().Equal(typeof (Resources.Data.Place)); 

    _socialWorkerMock.Verify(
     socialWorker => socialWorker.PlaceRepository.Add(It.IsAny<Resources.Data.Place>()), Times.Once()); 

    _placeRepositoryMock.Verify(
     placeRepository => 
     placeRepository.Find(p => p.Name.Equals(_place.Name), null, null).First(), 
     Times.Once()); 
} 

このテストの最後の検証は、このエラーで失敗します。

System.NotSupportedException : Invalid verify on a non-virtual (overridable in VB) member: placeRepository => placeRepository.Find(p => p.Name.Equals(._place.Name), null, null).First<Place>() 

私は一般的にMoqと単体テストにはかなり新しいです。

IUnitOfWork

public interface IUnitOfWork : IDisposable 
{ 
    void CommitChanges(); 
} 

IRepository

public interface IRepository<T> 
{ 
    void Add(T entity); 

    void Delete(T entity); 

    IEnumerable<T> Find(Expression<Func<T, bool>> filter = null, 
         Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, 
         IList<string> includedProperties = null); 

    T FindById(object id); 

    void Update(T entity); 
} 

DataWorker

public abstract class DataWorker : IUnitOfWork 
{ 
    protected ObjectContext ObjectContext; 
    private bool _disposed; 

    protected DataWorker() 
    { 
     ObjectContext = new ObjectContext(ConfigurationManager.ConnectionStrings["DataEntities"].ConnectionString); 
    } 

    ~DataWorker() 
    { 
     . . . 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     . . . 
    } 

    public virtual void CommitChanges() 
    { 
     ObjectContext.SaveChanges(); 
    } 

    public void Dispose() 
    { 
     . . . 
    } 
} 
:ここ

はあなたの参照のために関連するコードです

DataRepository

public class DataRepository<T> : IRepository<T> where T : EntityObject 
{ 
    private readonly ObjectSet<T> _objectSet; 

    public DataRepository(ObjectContext objectContext) 
    { 
      _objectSet = objectContext.CreateObjectSet<T>(); 
    } 

    public void Add(T entity) 
    { 
     . . . 
    } 

    public void Delete(T entity) 
    { 
     . . . 
    } 

    public virtual IEnumerable<T> Find(Expression<Func<T, bool>> filter = null, 
           Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, 
           IList<string> includedProperties = null) 
    { 
     . . . 
    } 

    public T FindById(object id) 
    { 
     . . . 
    } 


    public void Update(T entity) 
    { 
     . . . 
    } 
} 

SocialWorker

public class SocialWorker : DataWorker 
{ 
    private IRepository<ContactRequest> _contactRequestRepository; 
    private IRepository<Place> _placeRepository; 
    private IRepository<User> _userRepository; 

    public virtual IRepository<ContactRequest> ContactRequestRepository 
    { 
     get 
     { 
      return _contactRequestRepository ?? 
        (_contactRequestRepository = new DataRepository<ContactRequest>(ObjectContext)); 
     } 
    } 

    public virtual IRepository<Place> PlaceRepository 
    { 
     get { return _placeRepository ?? (_placeRepository = new DataRepository<Place>(ObjectContext)); } 
    } 

    public virtual IRepository<User> UserRepository 
    { 
     get { return _userRepository ?? (_userRepository = new DataRepository<User>(ObjectContext)); } 
    } 
} 

答えて

2

私はあなたのコードがやろうとしているかについて困惑している、デザインが少し奇妙に思えます。

まず、問題があるテストでは指定していないクラスPlaceManagerを参照しています。テストの一部であるため、どこが間違っているのかが分かりません。

また、私はPlaceManagerの目的がわかりません。あなたのデザインはPlaceRepositoryを提供するプロパティーを持つSocialWorkerを持っていますので、PlaceManagerは何ですか?なぜそれがSocialWorkerに渡されていますか? SocialWorkerはそれ自身PlaceRepositoryを管理していませんか?

なぜ_socialWorker.PlaceRepository.Add(place)に電話をしていないのですか、それとももっときれいです?

私だけPlaceMangerSocialWorker.PlaceRepositoryにアクセスすることを推測しているが、SocialWorker.PlaceRepositoryはパブリックプロパティがあるとして、直接使用するとPlaceManagerを無視して、誰を停止するには何もない、なぜ私は表示されません。 PlaceManagerPlaceの場合はRepositoryのようなものです。

また、IRepositoryコードはAdd()のコードが無効ですが、PlaceManagerobjectを返します。 Placeに強く型付けされていないのはなぜですか?それはあなたが期待しているようだ...PlaceManager.Add()メソッドは、RepositoryAdd()メソッドがvoidですが、Placeを返します。 (それは文脈に固執された後も同じ場所ですか?)PlaceManagerPlaceで何か他のことをしていますか?

おそらく私は棒の間違った終わりを持っていますか?あなたのコードの目的が何であるかについて、さらに明確にすることができますか?ご迷惑をおかけして申し訳ありませんが、私はあなたのデザインが何をしているのかを知りたいと思っています。

私は特定のしかし、Findに対する検証が期待されていることを確認するには、First()への呼び出しが含まれています。これは仮想化や抽象化ではなく静的な拡張メソッドなので、偽装する必要があります。

とにかくFirst()を相手にしている理由がわかりません。あなたが検証している方法は、単にある:それは、リポジトリ内のメソッドのシグネチャだとして実際に、呼び出されるものだ

_placeRepositoryMock.Verify(placeRepository => 
    placeRepository.Find(p => p.Name.Equals(_place.Name), null, null), 
    Times.Once()); 

。インターフェイスメソッドが呼び出されたかどうかのみ確認できます。

+0

これはMVCアプリケーションです。私は自分のコントローラから直接_socialWorker.PlaceRepository.Add(場所)を呼び出すことができました。しかし、コントローラをできるだけ薄く保つことを好みます。さらに、 'PlaceManager'は通常の' CRUD'以上のことをします。たとえば、Yahoo!のPlaceFinderサービスから関連する場所を探すなどです。さらに 'PlaceManager'が存在するので、将来、Services/APIモジュールは' UnitWorker'や 'Repository'に対してコードを直接記述することなく、同じビットのコードにアクセスすることができます。 – Moon

+0

'PlaceManager'と' PlaceRepository'の違いはまだわかりません。いつPlaceManagerに直接アクセスするのか、PlaceManagerを介してアクセスするのでしょうか?(結局のところ、 'PlaceManager'を無視する人はいません)。 'PlaceManager'が' PlaceRepository'を担当しないのはなぜですか?それは本当に私の匂いのように思えます、それはSRPに従っていないようです(ソーシャルワークはあまりにも多くのことをしており、 'Place'sは分割されています)。 'Place'は少なくとも2か所で追加できますが、私は全体的なデザインコンセプトを理解していないので、私にとって混乱しているようです。 – nicodemus13

+0

私のコントローラは、ワーカーまたはリポジトリが存在することさえ知りません。彼らがアクセスできるのはマネージャーだけです。 – Moon

関連する問題