I am using Moq framework for Mocking.
I have a SocialWorker which derives from an abstract DataWorker class.
The SocialWorker has reference to couple of Repositories as a virtual 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 verification of this test fails with this error:
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 fairly new to Moq and unit testing in general.
Here is the relevant code for your 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)); }
}
}
I’m confused about what your code is trying to do, the design seems a bit odd.
Firstly, the test you have a problem with is referencing a class
PlaceManager, which you haven’t specified and as that’s part of the test, it’s difficult to see quite where it’s going wrong.Furthermore, I’m not sure what PlaceManager is for. Your design has
SocialWorkerwith a property providing thePlaceRepository, so what is thePlaceManagerfor, and why is it being passed aSocialWorker? Doesn’tSocialWorkermanage its ownPlaceRepository?Why aren’t you calling
_socialWorker.PlaceRepository.Add(place), or rather more neatly_socialWorker.Add(place)?I’m only guessing that
PlaceMangeraccesses theSocialWorker.PlaceRepository, but I don’t see why as theSocialWorker.PlaceRepositoryis a public property, there’s nothing to stop anyone using directly and ignoring thePlaceManager. That’s if thePlaceManageris also some sort ofRepositoryforPlace.Also, your
IRepositorycode hasAdd()as a void, yet thePlaceManagerreturns anobject. Why is this not strongly-typed toPlace? It seems that is what you’re expecting… And yourPlaceManager.Add()method returns aPlace, though theRepositoryAdd()method isvoid. (is it the same place after it has been persisted to the context?) Is yourPlaceManagerdoing something else with thePlace?Perhaps I have the wrong end of the stick? Could you clarify more what the intent of your code is, over what it does? Sorry for so many questions, but I’d like to know what your design is supposed to be doing before figuring out why you’re trying to verify against a non-virtual…
I think the cause of the specific problem, is that in your verify you’re expecting a verify against the
Find, however, that includes a call toFirst(), which needs to be mocked and can’t be, as it’s a static extension method, not virtual or abstract.I’m not sure why you’re calling against
First(), anyway. The method you’re verifying is just:That’s what will actually be called, as that’s the signature of the method in the repository. You can only check that the interface method is called.