帮助我测试 NHibernate 和 NUnit 的一对多关系

发布于 2024-08-02 06:08:46 字数 6267 浏览 4 评论 0 原文

我有一个类 Task,它有一个属性 TaskLibrary,它是一个 dll,它将从中加载并运行一些代码。因此,任何任务都有一个库,但任何库都可以有多个任务。我的问题是,确保任务的 Library 属性不为 null 的测试失败了(所以这可能只是我的测试)。我的类实际上是这样的:

public class Task
{
  public virtual int TaskId {get;set;}
  public virtual string Locked {get;set;}
  public virtual int Status {get;set;}
  public virtual TaskLibrary Library {get;set;}
}

public class TaskLibrary
{
  public virtual int LibraryId {get;set}
  public virtual string Name {get;set;}
  public virtual string Description {get;set;}
  public virtual byte[] Dll {get;set}
  public virtual IEnumerable<Task> Tasks {get;set;}
}

我的 NHibernate 映射看起来像这样:

  <class name="Task">
    <id name="Id" column="TaskId" type="Int32" unsaved-value="-1">
      <generator class="identity"/>
    </id>
    <property name="Locked" column="Locked"/>
    <property name="Status" column="Status"/>
    <many-to-one name="Library" class="TaskLibrary" fetch="join"/>
  </class>
  <class name="TaskLibrary">
    <id name="Id" column="LibraryId">
      <generator class="identity"/>
    </id>
    <property name="Name"/>
    <property name="Description"/>
    <property name="Dll"/>
    <set name="Tasks" lazy="true">
      <key column="LibraryId"/>
      <one-to-many class="Task"/>
    </set>
  </class>

我的测试类看起来像这样:

[TestFixture]
public class TaskRepositoryFixture
{
    private ISessionFactory _sessionFactory;
    private Configuration _configuration;

    private readonly Task[] _tasks = new[]
        {
            new Task {Id = 1, Status = 1, Locked = 0, Library = new TaskLibrary { Id =1, Description = "Test Library", Name = "Tast.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
            new Task {Id = 2, Status = 1, Locked = 0, Library = new TaskLibrary { Id =1, Description = "Test Library", Name = "Tast.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
            new Task {Id = 3, Status = 1, Locked = 0, Library = new TaskLibrary { Id =2, Description = "Test Library 2", Name = "Tast2.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
            new Task {Id = 4, Status = 1, Locked = 0, Library = new TaskLibrary { Id =2, Description = "Test Library 2", Name = "Tast2.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
            new Task {Id = 5, Status = 1, Locked = 0, Library = new TaskLibrary { Id =3, Description = "Test Library 3", Name = "Tast3.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
        };

    private readonly TaskLibrary[] _libraries = new[]
        {
            new TaskLibrary { Id =1, Description = "Test Library", Name = "Tast.dll", Type = "RunnableTask", BinaryDll = Encoding.ASCII.GetBytes("test binary data")},
            new TaskLibrary { Id =2, Description = "Test Library 2", Name = "Tast2.dll", Type = "RunnableTask", BinaryDll = Encoding.ASCII.GetBytes("test binary data")},
            new TaskLibrary { Id =3, Description = "Test Library 3", Name = "Tast3.dll", Type = "RunnableTask", BinaryDll = Encoding.ASCII.GetBytes("test binary data")}
        };

    private void CreateInitialData()
    {
        using (ISession session = _sessionFactory.OpenSession())
        using (ITransaction transaction = session.BeginTransaction())
        {
            foreach (var lib in _libraries)
                session.Save(lib);

            foreach (var task in _tasks)
                session.Save(task);

            transaction.Commit();
        }
    }


    [TestFixtureSetUp]
    public void TestFixtureSetUp()
    {
        _configuration = new Configuration();
        _configuration.Configure();
        _configuration.AddAssembly("DistPollAutoTasksShared");
        _sessionFactory = _configuration.BuildSessionFactory();
    }

    [SetUp]
    public void SetupContext()
    {
        new SchemaExport(_configuration).Execute(false, true, false, false);
        CreateInitialData();
    }

    [Test]
    public void CanGetLibraryFromTask()
    {
        ITaskRepository repository = new TaskRepository();
        var fromDb = repository.GetById(_tasks[0].Id);
        Assert.IsNotNull(fromDb.Library);
        Assert.IsNotNull(fromDb.Library.Dll);
    }
  }

而且,MSSQL2000 数据库中的任务表是这样的:

CREATE TABLE [dbo].[Tasks](
    [TaskId] [int] IDENTITY(1,1) NOT NULL,
    [TaskLibrary] [int] NOT NULL,
    [Status] [int] NOT NULL,
    [Locked] [int] NOT NULL
)

如果你仍然和我在一起...

从我的任务类中,我只想Library 属性的 TaskLibrary 类的实例。另外,如果我正在使用库本身,我希望能够延迟检索使用该库的所有任务的 IEnumerable。但是,当我运行测试时,我收到此错误:

TestCase 'DistPollAutoTasksShared.Tests.TaskRepositoryFixture.CanGetLibraryFromTask'
failed: NHibernate.LazyInitializationException : Could not initialize proxy - no Session.
    at NHibernate.Proxy.AbstractLazyInitializer.Initialize()
    at NHibernate.Proxy.AbstractLazyInitializer.GetImplementation()
    at NHibernate.Proxy.Poco.Castle.CastleLazyInitializer.Intercept(IInvocation invocation)
    at Castle.DynamicProxy.AbstractInvocation.Proceed()
    at TaskLibraryProxy2bd44073e90f47298039abfbfda11492.get_Dll()

这是我第一次使用 NHibernate,所以我仍在学习。我真的很想打下良好的基础,所以我一直被困在这里直到那时。任何帮助、建议、阅读材料(我已阅读所有这个问题的建议和其他一些建议)将不胜感激。

编辑:

更改 fetch="join" 后,我从 Task 类中获得了我想要的功能。但是,我为 TaskLibrary 类的 Tasks 属性添加了另一个测试:

    [Test]
    public void CanGetTasksByLibrary()
    {
        ITaskLibraryRepository repository = new TaskLibraryRepository();
        var fromDb = repository.GetById(_libraries[0].Id).Tasks;

        Assert.IsNotNull(fromDb);
        Assert.True(fromDb.Count() == 2, "Cannot get IEnumerable<Task> from TaskLibrary");
    }

但是,断言因此错误而失败(我已更新上面的代码以反映我所做的任何更改):

TestCase 'DistPollAutoTasksShared.Tests.TaskLibraryRepositoryFixture.CanGetTasksByLibrary'
failed: 
  Cannot get IEnumerable<Tasks> from TaskLibrary
  Expected: True
  But was:  False

I have a class, Task, and it has a property TaskLibrary which is dll it will load and run some code from. So, any task has one library, but any library can have many tasks. My problem is that my test for making sure the task's Library property is not null is failing (so it could just be my test). My classes are effectively this:

public class Task
{
  public virtual int TaskId {get;set;}
  public virtual string Locked {get;set;}
  public virtual int Status {get;set;}
  public virtual TaskLibrary Library {get;set;}
}

public class TaskLibrary
{
  public virtual int LibraryId {get;set}
  public virtual string Name {get;set;}
  public virtual string Description {get;set;}
  public virtual byte[] Dll {get;set}
  public virtual IEnumerable<Task> Tasks {get;set;}
}

My NHibernate mappings look like this:

  <class name="Task">
    <id name="Id" column="TaskId" type="Int32" unsaved-value="-1">
      <generator class="identity"/>
    </id>
    <property name="Locked" column="Locked"/>
    <property name="Status" column="Status"/>
    <many-to-one name="Library" class="TaskLibrary" fetch="join"/>
  </class>
  <class name="TaskLibrary">
    <id name="Id" column="LibraryId">
      <generator class="identity"/>
    </id>
    <property name="Name"/>
    <property name="Description"/>
    <property name="Dll"/>
    <set name="Tasks" lazy="true">
      <key column="LibraryId"/>
      <one-to-many class="Task"/>
    </set>
  </class>

My test class looks like this:

[TestFixture]
public class TaskRepositoryFixture
{
    private ISessionFactory _sessionFactory;
    private Configuration _configuration;

    private readonly Task[] _tasks = new[]
        {
            new Task {Id = 1, Status = 1, Locked = 0, Library = new TaskLibrary { Id =1, Description = "Test Library", Name = "Tast.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
            new Task {Id = 2, Status = 1, Locked = 0, Library = new TaskLibrary { Id =1, Description = "Test Library", Name = "Tast.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
            new Task {Id = 3, Status = 1, Locked = 0, Library = new TaskLibrary { Id =2, Description = "Test Library 2", Name = "Tast2.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
            new Task {Id = 4, Status = 1, Locked = 0, Library = new TaskLibrary { Id =2, Description = "Test Library 2", Name = "Tast2.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
            new Task {Id = 5, Status = 1, Locked = 0, Library = new TaskLibrary { Id =3, Description = "Test Library 3", Name = "Tast3.dll", Type = "RunnableTask", Dll = Encoding.ASCII.GetBytes("test binary data")}},
        };

    private readonly TaskLibrary[] _libraries = new[]
        {
            new TaskLibrary { Id =1, Description = "Test Library", Name = "Tast.dll", Type = "RunnableTask", BinaryDll = Encoding.ASCII.GetBytes("test binary data")},
            new TaskLibrary { Id =2, Description = "Test Library 2", Name = "Tast2.dll", Type = "RunnableTask", BinaryDll = Encoding.ASCII.GetBytes("test binary data")},
            new TaskLibrary { Id =3, Description = "Test Library 3", Name = "Tast3.dll", Type = "RunnableTask", BinaryDll = Encoding.ASCII.GetBytes("test binary data")}
        };

    private void CreateInitialData()
    {
        using (ISession session = _sessionFactory.OpenSession())
        using (ITransaction transaction = session.BeginTransaction())
        {
            foreach (var lib in _libraries)
                session.Save(lib);

            foreach (var task in _tasks)
                session.Save(task);

            transaction.Commit();
        }
    }


    [TestFixtureSetUp]
    public void TestFixtureSetUp()
    {
        _configuration = new Configuration();
        _configuration.Configure();
        _configuration.AddAssembly("DistPollAutoTasksShared");
        _sessionFactory = _configuration.BuildSessionFactory();
    }

    [SetUp]
    public void SetupContext()
    {
        new SchemaExport(_configuration).Execute(false, true, false, false);
        CreateInitialData();
    }

    [Test]
    public void CanGetLibraryFromTask()
    {
        ITaskRepository repository = new TaskRepository();
        var fromDb = repository.GetById(_tasks[0].Id);
        Assert.IsNotNull(fromDb.Library);
        Assert.IsNotNull(fromDb.Library.Dll);
    }
  }

And, the Tasks table in the MSSQL2000 database is this:

CREATE TABLE [dbo].[Tasks](
    [TaskId] [int] IDENTITY(1,1) NOT NULL,
    [TaskLibrary] [int] NOT NULL,
    [Status] [int] NOT NULL,
    [Locked] [int] NOT NULL
)

If you're still with me...

From my Task class, I just want an instance of the TaskLibrary class for the Library property. Also, if I'm working with the libraries themselves, I want to be able to lazily retrieve an IEnumerable of all tasks using that library. However, when I run the test, I get this error:

TestCase 'DistPollAutoTasksShared.Tests.TaskRepositoryFixture.CanGetLibraryFromTask'
failed: NHibernate.LazyInitializationException : Could not initialize proxy - no Session.
    at NHibernate.Proxy.AbstractLazyInitializer.Initialize()
    at NHibernate.Proxy.AbstractLazyInitializer.GetImplementation()
    at NHibernate.Proxy.Poco.Castle.CastleLazyInitializer.Intercept(IInvocation invocation)
    at Castle.DynamicProxy.AbstractInvocation.Proceed()
    at TaskLibraryProxy2bd44073e90f47298039abfbfda11492.get_Dll()

This is the first time I've used NHibernate, so I'm still learning. I really want to get a good foundation of the basics, so I'm stuck here until then. Any help, suggestions, reading material (I've read all of this question's suggestions and some others) would be appreciated.

EDIT:

After changing fetch="join", I'm getting the functionality I want from the Task class. However, I've added another test for the Tasks property of the TaskLibrary class:

    [Test]
    public void CanGetTasksByLibrary()
    {
        ITaskLibraryRepository repository = new TaskLibraryRepository();
        var fromDb = repository.GetById(_libraries[0].Id).Tasks;

        Assert.IsNotNull(fromDb);
        Assert.True(fromDb.Count() == 2, "Cannot get IEnumerable<Task> from TaskLibrary");
    }

But, an assertion fails with this error (I've updated the code above to reflect any changes I've made):

TestCase 'DistPollAutoTasksShared.Tests.TaskLibraryRepositoryFixture.CanGetTasksByLibrary'
failed: 
  Cannot get IEnumerable<Tasks> from TaskLibrary
  Expected: True
  But was:  False

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦一生花开无言 2024-08-09 06:08:46
<many-to-one name="Library" class="TaskLibrary" fetch="join" />

这将在每次选择时加入库。

<many-to-one name="Library" class="TaskLibrary" lazy="false" />

这将急切地为库执行单独的选择。

否则,如果您仅设置 fetch="select" (这是默认值),它将延迟加载库。

http://ayende.com/ Blog/archive/2009/04/09/nhibernate-mapping-ltmany-to-onegt.aspx

http://nhibernate.info/doc/nh/en/index.html#collections-lazy

<many-to-one name="Library" class="TaskLibrary" fetch="join" />

This would join the Library on every select.

<many-to-one name="Library" class="TaskLibrary" lazy="false" />

This will eagerly execute separate select for the Library.

Otherwise, it will lazy load the Library if you only set fetch="select" (which is the default).

http://ayende.com/Blog/archive/2009/04/09/nhibernate-mapping-ltmany-to-onegt.aspx

http://nhibernate.info/doc/nh/en/index.html#collections-lazy

九命猫 2024-08-09 06:08:46

不要更改测试的映射,您的需求应该决定对象的映射方式。
您的存储库方法在从数据库获取后关闭会话。您需要在整个测试方法中保持会话打开。
要弄清楚如何做到这一点,您需要告诉我们您如何管理您的会话。这些是否与事务/线程本地相关?

Dont change the mapping for the test , your requirements should drive how objects are mapped .
Your repository method is closing the session after fetching fromDB. You need to keep the session open for the whole test method.
To figure out how to do that you need to tell us how you are managing your session . Are those tied to a transaction / threadlocal ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文