我是模拟测试的新手,我使用RhinoMock创建了一个单元测试。 第一个存根正在运行,但第二个正在抛出Null Exception,代码如下。
[TestMethod]
public void TestMethod1()
{
SetUp(); //bind List ftsController and ftsEreceiptNumberPrefix
MockRepository mocks = new MockRepository();
var ftsUnitOfWork = mocks.StrictMock<IFtsUnitOfWork>();
ftsUnitOfWork.Stub(x => x.Repository<FtsController>().Get()).Return(ftsController.AsQueryable());
ftsUnitOfWork.Stub(x =>
{
if (x.Repository<FtsPrefix>() == null)
{
throw new ArgumentNullException("Input cannot be null");
}
x.Repository<FtsPrefix>().Get();
}).Return(ftsPrefix.AsQueryable());
;
BoGeneratePrefix generateEreceiptPrefix = new BoGeneratePrefix (logger,ftsUnitOfWork);
generatePrefix.ProcessJob(null);
}
ProcessJob:
public class BoGeneratePrefix : IBoDataPurging
{
#region private Variables
private readonly ILogger _logger;
private readonly IUnitOfWork _ftsUnitOfWork;
private readonly string _defaultTraceCategory;
#endregion
#region BoGeneratePrefix Constructor
/// <summary>
/// Initialized class oject BoGeneratePrefix
/// </summary>
/// <param name="logger"></param>
/// <param name="ftsUoW"></param>
public BoGeneratePrefix(ILogger logger, IFtsUnitOfWork ftsUoW)
{
_defaultTraceCategory = GetType().Name;
_logger = logger;
_ftsUnitOfWork = ftsUoW;
}
public void ProcessJob(Configuration hconfiguration)
{
try
{
var lstController = _ftsUnitOfWork.Repository<FtsController>().Get().Select(x => x. Id).Distinct().AsNoTracking();
foreach (var Id in lstController.ToList())
{
var prefix = _ftsUnitOfWork.Repository<FtsPrefix>()
.Get(x => x. Id == Id
&& x.Status == Constants.NotPrefix).Count();
var ignoreForLowerSafePoint =
_ftsUnitOfWork.Repository<ConfigurationParameter>()
.Get(y => y.ParamType == Constants.IgnoreForLowerSafePoint &&
y.ParamName == Id)
.AsNoTracking()
.Select(t => t.ParamValues).SingleOrDefault();
var currentTime = DateTime.ParseExact(DateTime.Now.ToString(Constants.HHmmssTime),
Constants.HHmmssTime,
System.Globalization.CultureInfo.InvariantCulture).TimeOfDay;
if ( !( hconfiguration.StartTime <= currentTime
&& hconfiguration.EndTime >= currentTime))
{
return;
}
}
}
catch (Exception ex)
{
throw;
}
}
存储库:
public interface IRepository<TEntity> : IDisposable where TEntity : class
{
/// <summary>
/// Delete the record from the database by accepting the input parameter as id
/// </summary>
/// <param name="id">Parameter id is used to delete record from the database</param>
void Delete(object id);
/// <summary>
/// Delete the enity
/// </summary>
/// <param name="entityToDelete"></param>
void Delete(TEntity entityToDelete);
/// <summary>
/// Get Queryable by passing the Expression
/// </summary>
/// <param name="filter">this is used for filter parameter/Expression of query</param>
/// <param name="orderBy">Passing condition of orderBy for query</param>
/// <param name="includeProperties">Properties to be included in to the query while generating the query on filter/order by</param>
/// <returns>Entity type Queryable i.e. creates query depend upon accepted entity type as input parameter</returns>
#pragma warning disable S2360
IQueryable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "");
#pragma warning restore S2360
/// <summary>
/// Get Queryable by accepting the input parameter as modifiedSinceTimestamp
/// </summary>
/// <param name="modifiedSinceTimestamp"> modifiedSinceTimestamp </param>
/// <returns></returns>
IQueryable<TEntity> GetModifiedSince(long modifiedSinceTimestamp);
/// <summary>
/// Provides information of an entity by accepting the input parameters
/// </summary>
/// <param name="id">it gives the enity on the id condition </param>
/// <returns>Returns Entity </returns>
TEntity GetById(params object[] id);
/// <summary>
/// Inserts all changes made in this context as a Focus business transaction and enlists it for data insertion.
/// </summary>
/// <param name="entity">Entity i.e. object of generic type </param>
void Insert(TEntity entity);
/// <summary>
/// Gives information about which entity to update
/// </summary>
/// <param name="entityToUpdate">information about to update an enity</param>
void Update(TEntity entityToUpdate);
/// <summary>
///
/// </summary>
/// <param name="query"></param>
/// <param name="parameters"></param>
/// <returns></returns>
IEnumerable<TEntity> ExecWithStoreProcedure(string query, params object[] parameters);
/// <summary>
///
/// </summary>
/// <param name="entityToUpdate"></param>
void Detach(TEntity entityToUpdate);
}
UnitofWork -
public class FtsUnitOfWork : IFtsUnitOfWork
{
#region local variables
private readonly ILogger _logger;
private IFtsDbProvider _ftsDbProvider;
private readonly string _defaultTraceCategory;
private DbContext _context;
private Hashtable _repositories;
#endregion local variables
/// <summary>
/// Constructor for Fts Unit Of Work
/// </summary>
/// <param name="logger"></param>
/// <param name="ftsDbProvider"></param>
public FtsUnitOfWork(ILogger logger, IFtsDbProvider ftsDbProvider)
{
_defaultTraceCategory = GetType().Name;
_logger = logger;
_logger.WriteTrace("FtsUnitOfWork: Initializing", _defaultTraceCategory);
_ftsDbProvider = ftsDbProvider;
_context = new FtsDbContext(_logger, "FtsDbStore", _ftsDbProvider.GetFtsDbCompiledModel());
_logger.WriteTrace("FtsUnitOfWork: Initialized", _defaultTraceCategory);
}
/// <summary>
/// Saves all changes made in this context as a Focus business transaction and enlists it for data consolidation.
/// </summary>
/// <returns></returns>
public virtual int Save()
{
try
{
return _context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
throw new Exception("Optimistic_Concurrency_Check");
}
}
/// <summary>
///
/// </summary>
/// <param name="focusDtTransactionId"></param>
/// <returns></returns>
public int Save(Guid focusDtTransactionId)
{
return _context.SaveChanges();
}
/// <summary>
/// Generic Repository this function creates the Repository by accepting the parameter as Entity type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public IRepository<T> Repository<T>() where T : class
{
if (_repositories == null)
{
_repositories = new Hashtable();
}
var type = typeof(T).Name;
if (!_repositories.ContainsKey(type))
{
var repositoryType = typeof(Repository<>);
var repositoryInstance =
Activator.CreateInstance(repositoryType
.MakeGenericType(typeof(T)), _context);
_repositories.Add(type, repositoryInstance);
}
return (IRepository<T>)_repositories[type];
}
/// <summary>
///
/// </summary>
/// <typeparam name="T1"></typeparam>
/// <param name="sqlParameters"></param>
/// <param name="spName"></param>
/// <returns></returns>
public List<T1> GetMany<T1>(SqlParameter[] sqlParameters, string spName)
{
return _context.Database.SqlQuery<T1>(spName, sqlParameters).ToList();
}
/// <summary>
///
/// </summary>
/// <param name="isolationLevel"></param>
/// <returns></returns>
public DbContextTransaction GetDbContextTransaction(IsolationLevel isolationLevel)
{
return _context.Database.BeginTransaction(isolationLevel);
}
#region IDisposable Support
private bool _disposedValue; // To detect redundant calls
/// <summary>
///
/// </summary>
/// <param name="disposing"></param>
public virtual void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
_logger.WriteTrace("FtsUnitOfWork: Disposing", _defaultTraceCategory);
_ftsDbProvider = null;
_repositories = null;
this._context.Dispose();
this._context = null;
_logger.WriteTrace("FtsUnitOfWork: Disposed", _defaultTraceCategory);
}
_disposedValue = true;
}
}
/// <summary>
///
/// </summary>
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
如果我注释掉第一个存根,那么第二个存根正常工作,否则会抛出错误:
Fts.Services.Housekeeping.Tests.dll中发生了'System.ArgumentNullException'类型的异常,但未在用户代码中处理
附加信息:值不能为空。