我有一个NHibernate拦截器,它会覆盖Instanciate
方法,并执行以下操作:
虽然这听起来相当容易(并且已经有效),但如果我能通过单元测试证明其功能,我仍会感觉更好。
这是拦截器代码:
public override object Instantiate(string entityTypeName, EntityMode entityMode, object id)
{
// Type resolution across Assembly borders
Type type = TypeFinder.FindType(entityTypeName);
if (type == null)
{
throw new Exception(string.Format("",entityTypeName));
}
bool isViewModel = (typeof(ViewModelBase).IsAssignableFrom(type));
if (entityMode == EntityMode.Poco && isViewModel)
{
var instance = ProxyFactory.CreateProxy(type);
SessionFactory.GetClassMetadata(entityTypeName).SetIdentifier(instance, id, entityMode);
return instance;
}
return base.Instantiate(entityTypeName, entityMode, id);
}
我可以成功测试代理生成代码,但base.Instantiate
始终返回null。
这是我的测试代码(如你所见,我甚至添加了一个真正的数据库,以防Interceptor需要有效的会话):
private FluentConfiguration PrepareDataBase()
{
string connectionString = @"Data Source=test.sdf;";
SqlCeEngine en = new SqlCeEngine(connectionString);
en.CreateDatabase();
FluentConfiguration fc = Fluently.Configure().Database(MsSqlCeConfiguration.Standard
.ConnectionString(c => c.Is(connectionString))
.ShowSql())
.Mappings(x => x.FluentMappings.AddFromAssemblyOf<ViewModel>());
new SchemaExport(fc.BuildConfiguration()).Create(true, true);
return fc;
}
[TestMethod]
[DeploymentItem("System.Data.SqlServerCe.dll")]
public void Test_Instantiate_WithNonViewModelBasedPoco_ReturnsInstance()
{
TypeFinder.RegisterAssembly(typeof(OtherPoco).Assembly);
FluentConfiguration fc = PrepareDataBase();
NhChangeNotificationInterceptor interceptor = new NhChangeNotificationInterceptor();
ISession session = fc.BuildSessionFactory().OpenSession(interceptor);
string instanceType = typeof(OtherPoco).FullName;
object instance = interceptor.Instantiate(instanceType, EntityMode.Poco, null);
Assert.AreEqual(typeof(OtherPoco).FullName, instance.GetType().FullName);
Assert.IsFalse(typeof(ViewModelBase).IsAssignableFrom(instance.GetType()));
}
我认为这可能是null标识符的问题,所以我保存了一条记录,并尝试添加其ID,如下所示:
NhChangeNotificationInterceptor interceptor = new NhChangeNotificationInterceptor();
ISession session = fc.BuildSessionFactory().OpenSession(interceptor);
using (ITransaction trx = session.BeginTransaction())
{
session.Save(new OtherPoco() { Id = 1 });
session.Flush();
}
string instanceType = typeof(OtherPoco).FullName;
object instance = interceptor.Instantiate(instanceType, EntityMode.Poco, 1);
但是,不会改变任何东西。
知道我如何测试base.Instantiate
吗?
答案 0 :(得分:2)
我不会尝试为此编写单元测试。拦截器与NH /数据库紧密耦合 - 为此编写集成测试更好。
请勿尝试测试您的代码行。相反,测试您的功能。您已经说明了拦截器应该做什么(&#34;如果要实例化的类继承某个基类,则返回CastleDynamicProxy,否则只是实例化该类&#34;)。测试这个!如果你以后想要使用除拦截器之外的其他技术来获得相同的结果,那么你就不应该被迫修改你的测试。
因此,不要直接从您的测试中调用interceptor.Instantiate,而是进行一些集成测试,以验证它在从db中获取数据时应该执行的操作。