3

Moqモック用のフレームワークを使用しています。

クラスSocialWorkerから派生したを持っています。abstract DataWorker

としてのSocialWorkerカップルへの参照がありますRepositoriesvirtual property

次のテストを実行しようとしています。

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)); }
    }
}
4

1 に答える 1

3

あなたのコードが何をしようとしているのか混乱しています。デザインは少し奇妙に思えます。

まず、問題のあるテストは、PlaceManager指定していないクラスを参照していることです。これはテストの一部であるため、どこで問題が発生しているかを確認するのは困難です。

さらに、PlaceManagerが何のためにあるのかわかりません。あなたのデザインにはSocialWorker、を提供するプロパティがありますPlaceRepository。それで、何のPlaceManagerために、そしてなぜそれが渡されるのSocialWorkerですか?SocialWorker自分で管理しませんPlaceRepositoryか?

なぜあなたは電話をかけないのですか_socialWorker.PlaceRepository.Add(place)、それとももっときちんと電話をかけないのです_socialWorker.Add(place)か?

PlaceMangerにアクセスするのは推測しているだけですが、が公共の財産であるため、直接使用してを無視する人を止めるものが何もないSocialWorker.PlaceRepository理由はわかりません。それは、もある種のの場合です。SocialWorker.PlaceRepositoryPlaceManagerPlaceManagerRepositoryPlace

また、IRepositoryコードにはAdd()voidがありますが、は。をPlaceManager返しますobject。なぜこれは強く型付けされていないのPlaceですか?それはあなたが期待していることのようです...そしてあなたのメソッドは。ですが、あなたのPlaceManager.Add()メソッドはを返します。(それが文脈に永続化された後、それは同じ場所ですか?)あなたは?で何か他のことをしていますか?PlaceRepository Add()voidPlaceManagerPlace

おそらく私はスティックの端が間違っていますか?コードが何をするのかということよりも、コードの意図が何であるかをもっと明確にできますか?非常に多くの質問をして申し訳ありませんが、非仮想に対して検証しようとしている理由を理解する前に、あなたのデザインが何をしているのかを知りたいです...

特定の問題の原因は、検証で、に対する検証を期待していることだと思います。Findただし、これには、をFirst()モックする必要があり、静的拡張メソッドであるため、モックする必要はありません。仮想または抽象。

とにかく、なぜあなたが反対しているのかわかりませFirst()ん。確認する方法は次のとおりです。

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

これが実際に呼び出されるものです。これは、リポジトリ内のメソッドのシグネチャであるためです。インターフェイスメソッドが呼び出されていることのみを確認できます。

于 2012-04-07T13:09:49.420 に答える