user3527975
user3527975

Reputation: 1773

How to attach a moq entity to a mock datacontext

I am new to the idea of mocking and I am using Moq to unit test this code.

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;
         }
      }
   }
}

I want to test the method GetForumById. For this I want to create a mock of the ProForumDataContext and insert a mock forum into it. How should I setup the mock for ProForumDataContext so that when I call a GetTable method on it, it returns a table containing the mocked forum. Table is System.Data.Linq.Table class.

I was doing something like this:

[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();
}

I am not getting what to pass to the setup and what to return. Forum Class:

[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();
                }
            }
    }

Upvotes: 0

Views: 2681

Answers (2)

Brian Mains
Brian Mains

Reputation: 50728

I personally wouldn't recommend mocking the datacontext. There are complexities in the design of LINQ to SQL or ENtity Framework. The problem with DataContext is it establishes the connection in the constructor, and thus you end up not being isolated from the dependency on the database.

I'd instead recommend a class that wraps it, which also defines an interface, and use that interface reference everywhere you need it, which it could have methods like:

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

And implement whatever other methods you use. It will be much simpler.

Upvotes: 1

Ryan Burbidge
Ryan Burbidge

Reputation: 192

You can use Moq to mock interfaces, not classes. You would need an interface for ProForumDataContext (e.g. IProForumDataContext) with a method that returns GetTable(). You then need to change the ForumRepository to accept IProForumDataContext.

You would then mock like this:

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

But let's step back a bit. Your code could be more testable. Is there a reason why ForumRepository constructor accepts a ProForumDataContext? It could just accept the Table directly. This is called "pass methods what they need."

Not sure where you Forum class comes from, but you would need an interface to mock that as well.

Upvotes: 0

Related Questions