Moq, abstract class and virtual properties

I am using frameworks Moq

for Mocking.

I have SocialWorker

one that comes from a class abstract DataWorker

.

SocialWorker

has a pair link Repositories

likevirtual property

I am trying to run the following test:

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

      

The last check of this test fails:

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>()

      

I am new to Moq and unit testing in general.

Here is the relevant code for reference:

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

      

+3


source to share


1 answer


I'm confused about what your code is trying to do, the design seems a little odd.

First, the test you are facing refers to a class PlaceManager

you did not specify, and as that part of the test, it is difficult to see where this is happening.

Also, I'm not sure what the PlaceManager is for. In your design, there is SocialWorker

a property that provides PlaceRepository

, so what is it PlaceManager

, and why is it passed SocialWorker

? Doesn't he manage SocialWorker

his own PlaceRepository

?

Why don't you call _socialWorker.PlaceRepository.Add(place)

, or rather more accurately _socialWorker.Add(place)

?

I only assume that it is PlaceManger

referring to SocialWorker.PlaceRepository

, but I do not understand why, since it SocialWorker.PlaceRepository

is a public property, there is nothing to stop anyone using directly and ignoring PlaceManager

. This if is PlaceManager

also a kind Repository

for Place

.

Also, your IRepository

code has Add()

both void but PlaceManager

returns object

. Why isn't it strongly typed for Place

? This seems to be what you expect ... And your method PlaceManager.Add()

returns Place

, although the method Repository

Add()

void

. (is it the same place after it was saved in context?) Is yours PlaceManager

something else with Place

?



Perhaps I have the wrong end of the stick? Could you please clarify what is the purpose of your code, how does it do it? Sorry for so many questions, but I would like to know what your design is supposed to do before figuring out why you are trying to check against non-virtual ...

I think the reason for the specific problem is that in your check, you are expecting a confirmation against Find

, however, which involves a call First()

that needs to be mocked and cannot be, since it is a static extension method and not virtual or abstract.

I'm not sure why you are calling against First()

, anyway. The method you are testing is simple:

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

      

What will actually be called as such in a method in the repository. You can only check if the interface method has been called.

+2


source







All Articles