代码之家  ›  专栏  ›  技术社区  ›  Bittercoder

计算NHibernate在单元测试中执行的查询数

  •  8
  • Bittercoder  · 技术社区  · 15 年前

    在代码的一些单元/集成测试中,我们希望检查代码是否正确使用了二级缓存。

    根据Ayende提供的代码:

    http://ayende.com/Blog/archive/2006/09/07/MeasuringNHibernatesQueriesPerPage.aspx

    public class QueryCounter : IDisposable
    {
        CountToContextItemsAppender _appender;
    
        public int QueryCount
        {
          get { return _appender.Count; }
        }
    
        public void Dispose()
        {
          var logger = (Logger) LogManager.GetLogger("NHibernate.SQL").Logger;
          logger.RemoveAppender(_appender);
        }
    
        public static QueryCounter Start()
        {
          var logger = (Logger) LogManager.GetLogger("NHibernate.SQL").Logger;
    
          lock (logger)
          {
            foreach (IAppender existingAppender in logger.Appenders)
            {
              if (existingAppender is CountToContextItemsAppender)
              {
                var countAppender = (CountToContextItemsAppender) existingAppender;
    
                countAppender.Reset();
    
                return new QueryCounter {_appender = (CountToContextItemsAppender) existingAppender};
              }
            }
    
            var newAppender = new CountToContextItemsAppender();
            logger.AddAppender(newAppender);
            logger.Level = Level.Debug;
            logger.Additivity = false;
    
            return new QueryCounter {_appender = newAppender};
          }
        }
    
        public class CountToContextItemsAppender : IAppender
        {
          int _count;
    
          public int Count
          {
            get { return _count; }
          }
    
          public void Close()
          {
          }
    
          public void DoAppend(LoggingEvent loggingEvent)
          {
            if (string.Empty.Equals(loggingEvent.MessageObject)) return;
            _count++;
          }
    
          public string Name { get; set; }
    
          public void Reset()
          {
            _count = 0;
          }
        }
    }
    

    预期用途:

    using (var counter = QueryCounter.Start())
    {
      // ... do something 
      Assert.Equal(1, counter.QueryCount); // check the query count matches our expectations
    }
    

    但查询计数总是返回0。没有记录sql语句。

    但是,如果我使用Nhibernate Profiler并在测试用例中调用它:

    NHibernateProfiler.Intialize()
    

    当NHProf使用类似的方法从NHibernate获取日志输出,以便通过log4net等进行分析时,我的QueryCounter就开始工作了。

    看起来我的代码中缺少了一些东西来正确配置log4net以记录nhibernate sql。。。有人对我还需要做些什么来从Nhibernate获取sql日志输出有任何指示吗?

    其他信息:

    <log4net>
    
      <appender name="trace" type="log4net.Appender.TraceAppender, log4net">
        <layout type="log4net.Layout.PatternLayout,log4net">
          <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] &amp;lt;%P{user}&amp;gt; - %m%n" />
        </layout>
      </appender>
    
      <appender name="console" type="log4net.Appender.ConsoleAppender, log4net">
        <layout type="log4net.Layout.PatternLayout,log4net">
          <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] &amp;lt;%P{user}&amp;gt; - %m%n" />
        </layout>
      </appender>
    
      <appender name="debug" type="log4net.Appender.DebugAppender, log4net">
        <layout type="log4net.Layout.PatternLayout,log4net">
          <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] &amp;lt;%P{user}&amp;gt; - %m%n" />
        </layout>
      </appender>
    
      <logger name="NHibernate.SQL" additivity="false">
        <level value="DEBUG" />
        <appender-ref ref="ConsoleAppender" />
      </logger>
    
      <root>
        <priority value="DEBUG" />
        <appender-ref ref="trace" />
        <appender-ref ref="console" />
        <appender-ref ref="debug" />
      </root>
    
    </log4net>
    

    显示sql:true

    基于jfneis的响应,我编写了一个简单得多的类,它只使用NHibernate的工厂统计:

    public class QueryCounter
    {
      long _startCount;
    
      QueryCounter()
      {
      }
    
      public int QueryCount
      {
        get { return (int) (UnitOfWork.CurrentSession.SessionFactory.Statistics.QueryExecutionCount - _startCount); }
      }
    
      public static QueryCounter Start()
      {
        return new QueryCounter {_startCount = UnitOfWork.CurrentSession.SessionFactory.Statistics.QueryExecutionCount};
      }
    }
    

    一旦启用了统计信息,它就可以正常工作。

    1 回复  |  直到 15 年前
        1
  •  13
  •   jfneis    15 年前

    如果缓存被命中或者查询被执行,还有另一种(更简单,IMO)断言方法:使用统计信息。

    首先,您必须在NH config文件中启用统计信息:

     <property name="generate_statistics">true</property>
    

    之后,您可以随时询问会话工厂情况。您已经谈到了二级缓存测试,所以您可以有这样的内容:

            // act
            MappedEntity retrievedEntity = session.FindById(entity.Id);
            long preCacheCount = sessionFactory.Statistics.SecondLevelCacheHitCount;
            retrievedEntity = session.FindById(entity.Id);
            long postCacheCount = sessionFactory.Statistics.SecondLevelCacheHitCount;
            // assert
            Assert.AreEqual(preCacheCount + 1, postCacheCount);
    

    但是,如果您真正想要的是查询计数,那么统计界面中还有很多其他选项:

            sessionFactory.Statistics.QueryExecutionCount;
            sessionFactory.Statistics.TransactionCount;
    

    好吧,就这样。希望这能像帮助我一样帮助你。

    当做,

    菲利佩