我正在使用Moq
框架進行Mocking。Moq,抽象類和虛擬屬性
我有一個SocialWorker
它來自abstract DataWorker
類。
的SocialWorker
具有參考夫婦Repositories
作爲virtual 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)); }
}
}
這是一個MVC應用程序。我可以直接從我的控制器調用_socialWorker.PlaceRepository.Add(place)。但我更願意讓我的控制器儘可能薄。而且'PlaceManager'不僅僅是正常的'CRUD'。例如,從雅虎的'PlaceFinder'服務中找到相關的地方。此外,還有'PlaceManager',以便將來服務/ API模塊可以訪問相同的代碼位,而不必直接針對'UnitWorker'或'Repository'編寫代碼。 – Moon 2012-04-07 14:36:33
我仍然不確定'PlaceManager'和'PlaceRepository'之間的區別是什麼。什麼時候會直接訪問'PlaceRepository',何時通過'PlaceManager'訪問(畢竟,沒有什麼能阻止任何人忽略'PlaceManager')。爲什麼'PlaceManager'不負責'PlaceRepository'?這真的對我來說似乎是一種嗅覺,它並沒有出現在SRP之後(SocialWorker做了太多的事情,並且'Place'的責任被分割了。 '地方'可以添加至少2個地方,我不瞭解整體設計概念,它似乎混淆了我。 – nicodemus13 2012-04-07 14:50:48
我的控制器甚至不知道存在工作人員或存儲庫。他們所有的權限都是經理。 – Moon 2012-04-07 18:36:40