在单元测试时,如何让 #if 条件工作?

How do you get a #if conditional to work when unit testing?

提问人: 提问时间:2/25/2009 最后编辑:Mihai Limbășan 更新时间:3/23/2009 访问量:350

问:

这就是我希望能够做到的。

/// <summary>
        /// Gets the session factory.
        /// </summary>
        /// <value>The session factory.</value>
        public ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                {
#if(NUNIT)
                     _sessionFactory = Fluently.Configure()
                        .Database(SQLiteConfiguration.Standard
                                      .UsingFile(DbFile)
                                      .ShowSql())
                        .Mappings(m =>
                                  m.FluentMappings.AddFromAssemblyOf<ForeignFormat>())
                        .ExposeConfiguration(BuildSchema)
                        .BuildSessionFactory();

#else
                    _sessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2005
                              .ConnectionString(c => c
                                                         .Server(".\\sqlexpress")
                                                         .Database("mPort")
                                                         .TrustedConnection())
                                                         .ShowSql()
                                               )

                .Mappings(m => m
                                   .FluentMappings.AddFromAssemblyOf<ForeignFormat>())
                .BuildSessionFactory();
#endif
                }
                return _sessionFactory;

            }
        }

如果运行单元测试,是否可以 #if 条件?

visual-studio-2008 单元测试 nunit 条件语句 if-statement

评论

0赞 eleven81 2/25/2009
下次,请尝试将您的问题格式更整齐一点!

答:

0赞 cmcginty 2/25/2009 #1

我不建议将这种方法用于单元测试。永远不要将“测试”代码放入生产文件中。

您应该研究模拟对象,以便从您的方法中获取所需的功能。BuildSessionFactory

1赞 Steven Evers 2/25/2009 #2

我建议嘲笑数据库连接,而不是通过你的代码乱扔 #if/#else(即使它只是在这个地方)。

评论

0赞 2/25/2009
我知道你应该在大多数单元测试中模拟你的数据库,但你如何测试与数据库的实际交互?FluentNH 将从您的映射中构建一个假数据库,这样我就可以对“真实数据库”运行单元测试,并能够看到 logForNet 推送的 NHibernate 查询
0赞 Sander Rijken 2/25/2009 #3

不应使用 #if 部分将测试代码与生产代码分开。您希望(并且需要)测试生产代码。

使数据库的类型/配置可配置可能更有意义。依赖注入是做到这一点的一种方法,你似乎正在使用的城堡框架就很容易做到这一点。

依赖关系注入是一种将您发布的代码与数据库的实际实现分离的技术。这意味着您可以在测试期间注入文件或完全伪造的数据库类。

评论

0赞 2/25/2009
SQLite 和 fluentNH 似乎从您的映射中生成了一个假数据库。我想将假数据库用于单元测试,将真实数据库用于生产代码。我知道这不是最佳实践。我只是在寻找一种在不使用生产数据库的情况下测试数据库交互的方法
0赞 Sander Rijken 2/25/2009
您本身不需要注入模拟数据库。也可以像在 #if 部分所做的那样注入假数据库,然后注入它。
2赞 AwesomeTown 2/25/2009 #4

#if 是一个编译器指令,因此在运行测试时需要以不同的方式编译代码,而不是在“实际”运行测试时编译代码。为此,您可以在项目的生成设置中定义编译器标志。

但是,我同意其他人的观点,他们认为这不是一个好方法。除了人们提到的其他问题之外,当您想在运行单元测试和运行实际应用程序之间切换时,不断重新编译将是一件痛苦的事情。

依赖注入或嘲讽会更好地为您服务。

0赞 philant 2/25/2009 #5

除了 SessionFactory 之外,为什么不在单元测试中创建一个 FakeSessionFactory 呢?

在单元测试中,你向你的客户端类传递一个 FakeSessionFactory 实例,在你的应用程序中,你为他提供一个 SessionFactory,以便它真正访问数据库。

        public ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                {
                    _sessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2005
                              .ConnectionString(c => c
                                                         .Server(".\\sqlexpress")
                                                         .Database("mPort")
                                                         .TrustedConnection())
                                                         .ShowSql()
                                               )

                .Mappings(m => m
                                   .FluentMappings.AddFromAssemblyOf<ForeignFormat>())
                .BuildSessionFactory();
                }
                return _sessionFactory;
            }
        }

        public ISessionFactory FakeSessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                {
                     _sessionFactory = Fluently.Configure()
                        .Database(SQLiteConfiguration.Standard
                                      .UsingFile(DbFile)
                                      .ShowSql())
                        .Mappings(m =>
                                  m.FluentMappings.AddFromAssemblyOf<ForeignFormat>())
                        .ExposeConfiguration(BuildSchema)
                        .BuildSessionFactory();

                }
                return _sessionFactory;
            }
        }

评论

0赞 2/25/2009
Thanks... I'll look into this but I using the UnitOfWork pattern and this code behind a wrapper so its difficult to dictate the behavior I think my only solution is dependency injection