如何将moq实体附加到模拟datacontext

时间:2014-08-08 17:10:47

标签: c# linq unit-testing moq

我是嘲笑的新手,我正在使用Moq对这段代码进行单元测试。

using Forum = ProForum.Domain.Database.tblForum;
using Thread = ProForum.Domain.Database.tblThread;

namespace ProForum.Domain.Concrete
{
   public class ForumRepository : IForumRepository
   {
      protected Table<Forum> DataTable;
      private ProForumDataContext dataContext;

      public ForumRepository(ProForumDataContext dataContext)
      {
         DataTable = dataContext.GetTable<Forum>();
      }

      public Forum GetForumById(int id)
      {
         try
         {
            return DataTable.Single(f => f.tblForumID.Equals(id));
         }
         catch (Exception e)
         {
            return null;
         }
      }
   }
}

我想测试方法GetForumById。为此,我想创建一个ProForumDataContext的模拟并插入一个模拟论坛。我应该如何为ProForumDataContext设置模拟,这样当我在其上调用GetTable方法时,它会返回一个包含模拟论坛的表。表格为System.Data.Linq.Table类。

我做的是这样的事情:

[TestMethod]
public void Can_Get_Forum_ById()
{
   //arrange
   Mock<Forum> mockForum = new Mock<Forum>();
   mockForum.Object.tblForumID = 1;
   //Mock<Table<Forum>> tableMock = new Mock<Table<Forum>>();
   //tableMock.Object.Attach(mockForum);
   Mock<DiscussionForumDataContext> mockContext = new Mock<DiscussionForumDataContext>();
   mockContext.Setup).
   Returns();
}

我没有得到什么传递到设置和返回什么。 论坛类:

[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.tblForums")]
    public partial class tblForum : INotifyPropertyChanging, INotifyPropertyChanged
    {

        private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);

        private int _tblForumID;
        private string _Name;
        private string _Description;
        private int _tblUserLogin_ID;
        private int _TotalPosts;
        private int _TotalThreads;
        private bool _Active;
private System.Data.Linq.Binary _RowVersion;

        private System.DateTime _Modified;

        private System.DateTime _Created;

        private EntitySet<tblThread> _tblThreads;
        public tblForum()
        {
            this._tblThreads = new EntitySet<tblThread>(new Action<tblThread>(this.attach_tblThreads), new Action<tblThread>(this.detach_tblThreads));
            OnCreated();
        }

        [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_tblForumID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true, UpdateCheck=UpdateCheck.Never)]
        public int tblForumID
        {
            get
            {
                return this._tblForumID;
            }
            set
            {
                if ((this._tblForumID != value))
                {
                    this.OntblForumIDChanging(value);
                    this.SendPropertyChanging();
                    this._tblForumID = value;
                    this.SendPropertyChanged("tblForumID");
                    this.OntblForumIDChanged();
                }
            }
    }

2 个答案:

答案 0 :(得分:0)

您可以使用Moq来模拟接口,而不是类。您需要一个ProForumDataContext接口(例如IProForumDataContext)和一个返回GetTable()的方法。然后,您需要更改ForumRepository以接受IProForumDataContext。

然后你会这样嘲笑:

Mock<IProForumDataContext> mockContext = new Mock<IProForumDataContext>();
mockContext.Setup(context => context.GetTable<Forum>()).Returns(forum);

但是让我们退一步吧。您的代码可能更容易测试。 ForumRepository构造函数接受ProForumDataContext的原因是什么?它可以直接接受表。这被称为&#34;传递他们需要的方法。&#34;

不确定Forum类的来源,但您还需要一个界面来模拟它。

答案 1 :(得分:0)

我个人不建议模拟datacontext。 LINQ to SQL或ENtity Framework的设计存在复杂性。 DataContext的问题是它在构造函数中建立连接,因此最终不会与数据库的依赖关系隔离。

我会推荐一个包装它的类,它也定义了一个接口,并在你需要的任何地方使用该接口引用,它可以有以下方法:

public interface IUnitOfWork
{
   Table<T> GetTable();
   void SubmitChanges();
}

并实施您使用的任何其他方法。它会更简单。