加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – 如何为MVC创建具有1对多关联的虚假存储库

发布时间:2020-12-16 03:51:07 所属栏目:asp.Net 来源:网络整理
导读:我正在尝试使用具有一对多关系的类对象创建一个虚假的单元测试存储库.我正在使用ASP.NET MVC和 Linq to SQL.我的参考文献是Steven Sanderson的“Pro ASP.NET MVC框架”一书. 我用关联创建了实体类: [Table(Name = "Albums")]public class Album{ [Column(Is
我正在尝试使用具有一对多关系的类对象创建一个虚假的单元测试存储库.我正在使用ASP.NET MVC和 Linq to SQL.我的参考文献是Steven Sanderson的“Pro ASP.NET MVC框架”一书.

我用关联创建了实体类:

[Table(Name = "Albums")]
public class Album
{
    [Column(IsDbGenerated = true,IsPrimaryKey = true)]
    public int AlbumID { get; set; }
    [Column]
    public string Title { get; set; }

    private EntitySet<Track> _tracks;

    [Association(Storage = "_tracks",ThisKey = "AlbumID",OtherKey = "AlbumID")]
    public EntitySet<Track> Tracks
    {
        get { return _tracks; }
        set { _tracks.Assign(value); }
    }
}

[Table(Name = "Tracks")]
public class Track
{
    [Column(IsPrimaryKey = true)]
    public int TrackID { get; set; }
    [Column]
    public string Title { get; set; }
    [Column]
    public int AlbumID { get; set; }
}

以及存储库的抽象接口:

public interface IMusicRepository
{
    IQueryable<Album> Albums { get; }
    IQueryable<Track> Tracks { get; }
}

我能够为专辑创建一个虚假的存储库 – FakeMusicRepository:

public class FakeMusicRepository : IMusicRepository
{

    private static IEnumerable<Track> fakeTracks = new List<Track>
    {
        new Track {AlbumID = 1,TrackID = 1,Title = "Flood"},new Track {AlbumID = 1,TrackID = 2,Title = "Liquid"},new Track {AlbumID = 2,Title = "Song 1"},Title = "Song 2"}
    }.AsEnumerable();

    private static IQueryable<Album> fakeAlbums = new List<Album>
    {
          new Album {AlbumID = 1,Title = "Jars of Clay"},new Album {AlbumID = 2,Title = "Wind in the Wheat"}
    }.AsQueryable();


    public IQueryable<Album> Albums
    {
        get { return fakeAlbums; }
    }

    public IQueryable<Track> Tracks
    {
        get { return fakeTracks.AsQueryable(); }
    }

}

只要我不尝试访问任何曲目,哪个工作正常.换句话说,Album.Title可以工作,但访问Album.Tracks.Count()将生成一个空引用异常.我不确定Linq-To-SQL或Linq-To-Objects是否会拾取关联并自动将其与假对象一起使用.

问题在于,无论我尝试什么,似乎都无法将轨道分配给专辑类.我知道EntitySet基于IEnumerable,但是将Enumerable列表强制转换为EntitySet是一个挑战.

相册期待一个EntitySet,但我能够传递的唯一方法是通过自定义帮助:

public static class EntityCollectionHelper
{
    public static EntitySet<T> ToEntitySet<T>(this IEnumerable<T> source) where T : class
    {
        EntitySet<T> set = new EntitySet<T>();
        set.AddRange(source);
        return set;
    }
}

这跟我一样接近:

public class FakeMusicRepository2 : IMusicRepository
{
    private static IEnumerable<Track> fakeTracks = new List<Track>
    {
        new Track {AlbumID = 1,Title = "Song 2"}
    }.AsEnumerable();

    private static EntitySet<Track> Tracks1 = (from t in fakeTracks where t.AlbumID == 1 select t).ToEntitySet();
    private static EntitySet<Track> Tracks2 = (from t in fakeTracks where t.AlbumID == 2 select t).ToEntitySet();

    private static IQueryable<Album> fakeAlbums = new List<Album>
    {
          new Album {AlbumID = 1,Title = "Jars of Clay",Tracks=Tracks1},Title = "Wind in the Wheat",Tracks=Tracks2}
    }.AsQueryable();


    public IQueryable<Album> Albums
    {
        get { return fakeAlbums; }
    }

    public IQueryable<Track> Tracks
    {
        get { return fakeTracks.AsQueryable(); }
    }

}

但是,当我尝试访问Album.Tracks时,我得到了

System.NullReferenceException : Object reference not set to an instance of an object.

这是植入/单元测试:

[Test]
    public void Test_FakeMusicRepository()
    {
        // Arrange: Setup Repository
        var dc = new FakeMusicRepository2();

        // Act:
        var albums = dc.Albums.AsQueryable();
        // Load the first test location
        Album album = dc.Albums.First();

        // Assert: That there are records in the Album Object
        Assert.Greater(albums.Count(),"No Albums Records Returned!");

        //Assert that our first Album is not Null
        Assert.IsNotNull(album,"returned Album is Null!");
        // Assert: That we have the correct Album
        Assert.AreEqual(album.AlbumID,1,"Returned Album ID is not correct!");

        // Try to Count the related sub table (Tracks)
        var trackCount = album.Tracks.Count();

        // Try to get the first Track
        var track1 = album.Tracks.FirstOrDefault();


        // Assert: The Album has Tracks 
        Assert.Greater(trackCount,"Album has no Tracks");

        // Assert: That First track is not Null
        Assert.IsNotNull(track1,"Track1 object was Null!");

        // Assert: That Track1 has data
        Assert.IsNotNull(track1.TrackID,"Track1's ID was Null!");
    }

我花了几天时间寻找这个问题的答案,但没有找到任何例子,所以如果有人能够发布一个有效的答案,我相信其他人也会感兴趣.

我是MVC和单元测试的新手,所以请跟我一起轻松.我手边也有IoC和Moq,但我对这些知之甚少,但我打算同时使用这个项目.如果有更好的方法可以做到这一点,那么我全都耳朵!谢谢.

解决方法

专辑类似乎有点奇怪,尤其是这部分:

private EntitySet<Track> _tracks;

[Association(Storage = "_tracks",OtherKey = "AlbumID")]
public EntitySet<Track> Tracks
{
    get { return _tracks; }
    set { _tracks.Assign(value); }
}

永远不会为_tracks私有成员分配一个值,并在setter中调用Assign方法,该方法会抛出异常.顺便说一句,编译器应该警告你.在调用Assign方法之前,您可以尝试提供默认值或在setter中检查null:

private EntitySet<Track> _tracks = new EntitySet<Track>();

除了你的扩展方法转换IEnumerable< T>到EntitySet< T>看起来很好.

最后,当您分配假相册时,您需要设置曲目:

private static IQueryable<Album> fakeAlbums = new List<Album>
{
      new Album 
      {
          AlbumID = 1,Tracks = fakeTracks.ToEntitySet() 
      },new Album 
      {
          AlbumID = 2,Tracks = fakeTracks.ToEntitySet() 
      }
}.AsQueryable();

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读