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)); }
}
}
source to share
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.
source to share