我是单元测试的新手,我想要一些帮助.我首先使用存储库模式的代码.我有一个通用的存储库,其中包含称为Generic Repository的通用CRUD操作(请参阅打击)
public abstract class GenericRepository<T> where T : class
{
private HolidayDatabaseContext _dataContext;
private readonly IDbSet<T> _dbset;
protected GenericRepository(IDbFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
_dbset = DataContext.Set<T>();
}
protected IDbFactory DatabaseFactory
{
get;
private set;
}
protected HolidayDatabaseContext DataContext
{
get { return _dataContext ?? (_dataContext = DatabaseFactory.Get()); }
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Update(T entity)
{
_dataContext.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(T entity)
{
_dbset.Remove(entity);
}
public virtual IEnumerable<T> Enumerable()
{
return _dbset.AsEnumerable<T>();
}
public virtual IQueryable<T> List()
{
return _dbset.AsQueryable<T>();
}
public virtual T GetSingleById(int id)
{
return _dbset.Find(id);
}
public void Save()
{
_dataContext.SaveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
然后我将其继承到用户存储库并创建了一些特定的方法.见下文
public class UserRepository : GenericRepository<User>, IUserRepository
{
public UserRepository(IDbFactory databaseFactory)
: base(databaseFactory) { }
public int HolidayEntitlement(int userId)
{
return HolidayEntitlement(userId, DateTime.Now);
}
public int HolidayEntitlement(int userId, DateTime dateTime)
{
//Get the User
var user = this.GetSingleById(userId);
//Work Total Entitlement
int entitlement = user.BaseHolidayEntitlement;
//Years in Service
entitlement += (dateTime - user.EmploymentStartDate).Days / 365;
return entitlement;
}
public int RemainingHolidayEntitlement(int userId)
{
return RemainingHolidayEntitlement(userId, DateTime.Now);
}
public int RemainingHolidayEntitlement(int userId, DateTime dateTime)
{
return int.MinValue;
}
}
Run Code Online (Sandbox Code Playgroud)
我想单元测试HolidayEntitlement(int userId,DateTime dateTime),但我需要在方法中模拟GetSingleById部分
我把它写成了一个测试,但它没有编译.
[TestMethod]
public void GetHolidayEntitlement25()
{
//How to write this Unit test
//Setup
var user = new User { AnnualHolidayIncrement = 1, BaseHolidayEntitlement = 25, EmploymentStartDate = new DateTime(2013, 1, 1),Id=1 };
Mock<UserRepository> mock = new Mock<UserRepository>();
mock.Setup(m => m.GetSingleById(1)).Returns(user);
Assert.AreEqual(25, mock.Object.HolidayEntitlement(1));
}
Run Code Online (Sandbox Code Playgroud)
任何帮助,将不胜感激
Bel*_*gix 14
你似乎在说你只想模仿部分界面.当你开始遇到这种情况时,它表明你正在混淆你的担忧,并可能在某处做错事.
在这种情况下你的版本库做MUCH不仅仅是CRUD更多,因此具有多重责任(它应该只有一个,查找扎实的编程).您正在存储库中执行业务逻辑,它不应该存在!除了简单的CRUD操作之外的任何操作都应该移到业务逻辑层中.即你的HolidayEntitlement方法通过应用一些逻辑来计算某些东西,因此不是CRUD /存储库操作!
那么......你应该做的就是将业务逻辑位移到一个新类中,比如说UserLogic.在UserLogic类中,您将使用注入IUserRepository与存储库进行通信.在UserLogic那里你可以放置你的HolidayEntitlement方法,它会调用IUserRepository.GetSingleById.所以,当你再测试你的UserLogic课程时,你会在你的模拟IUserRepository中注入具有存根版本的模型GetSingleById,然后你会回到正确的轨道上!
我希望这有道理/有帮助吗?!
- 最后发布 -
PS我原来的帖子声明你应该模拟接口,而不是实例,所以这仍然适用,我将离开这里作为参考:
你应该嘲笑IUserRepository 不 UserRepository.
那是因为UserRepository是一个实现IUserRepository.你想说你给它一个新的实现,即你的模拟.目前您正在使用ACTUAL课程UserRepository.
当您需要提供假依赖时通常会使用模拟,在这种情况下,您似乎正在尝试模拟被测系统(SUT),这实际上没有意义 - 实际上没有意义,因为您的测试实际上并没有告诉您关于行为的任何事情UserRepository; 你正在做的就是测试你是否正确设置了Mock,这不是很有用!
您给出的测试代码似乎表明您要测试UserRepository.HolidayEntitlement.
我更倾向于将这样的函数从Repository类中移出到一个单独的业务逻辑类类中.通过这种方式,您可以测试在完全隔离中计算用户假期权利的逻辑,这是单元测试的主要原则.
为了测试这个函数做了它应该做的事情(即根据a的属性执行计算User),你需要确保User在该函数中操作的任何实例都是100%隔离并且在你的控制之下 - 或者用用户的模拟或伪造(Stub)实例,在这种情况下,Mocks是一个很好的选择,因为您只需要实现SUT将需要的依赖部分.
所以,你能做的就是:
为User定义一个界面
public interface IUser
{
int BaseHolidayEntitlement{get;set;}
DateTime EmploymentStartDate {get;set;}
//other properties for a User here
}
Run Code Online (Sandbox Code Playgroud)
在User类上实现此功能
public class User:IUser
{
//implemement your properties here
public int BaseHolidayEntitlement{get;set;}
public DateTime EmploymentStartDate {get;set;}
//and so on
}
Run Code Online (Sandbox Code Playgroud)
为用户逻辑创建一个类
public class UserRules
{
public int GetHolidayEntitlement(IUser user,DateTime dateTime)
{
//perform your logic here and return the result
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您的测试变得更加简单,甚至不需要存储库
[TestMethod]
public void GetHolidayEntitlement_WithBase25_Returns25()
{
//Arrange
var user = new Mock<IUser>();
//setup known, controlled property values on the mock:
user.SetupGet(u=>u.BaseHolidayEntitlement).Returns(25);
user.SetupGet(u=>u.EmploymentStartDate).Returns(new DateTime(2013,1,1));
var sut = new UserRules();
int expected = 25;
//Act
int actual = sut.GetHolidayEntitlement(user.Object,DateTime.UtcNow);
//Assert
Assert.AreEqual(expected,actual,"GetHolidayEntitlement isn't working right...");
}
Run Code Online (Sandbox Code Playgroud)