首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用具体类型模拟ITable

如何使用具体类型模拟ITable
EN

Stack Overflow用户
提问于 2014-08-14 16:50:17
回答 2查看 1.8K关注 0票数 1

我正在为使用System.Data.Linq DataConext对象从数据库获取实体表的存储库编写单元测试。下面是代码:

代码语言:javascript
复制
public class ForumRepository : IForumRepository
{
    protected Table<Forum> DataTable;
    IDataContextWrapper DataContext;

    public ForumRepository(IDataContextWrapper DataContext)
    {
        DataTable = DataContext.GetTable<Forum>();
    }

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

下面是包装器的实现:

代码语言:javascript
复制
public class DataContextWrapper<T> : IDataContextWrapper where T : EpixForumDataContext, new()
{
    private readonly T db;

    public DataContextWrapper()
    {
        var t = typeof(T);
        db = (T)Activator.CreateInstance(t);
    }
    public DataContextWrapper(string connectionString)
    {
        var t = typeof(T);
        db = (T)Activator.CreateInstance(t, connectionString);
    }

    public Table<TableName> GetTable<TableName>() where TableName : class
    {
        return (Table<TableName>)db.GetTable(typeof(TableName));
    }

我想测试存储库方法。

代码语言:javascript
复制
public class UnitTest1
    {
        [TestMethod]
        public void Can_Get_Forum_ById()
        {
            //arrange
            Forum dummyForum = new Forum() { tblForumID = 1};
            Mock<ITable<Forum>> tableMock = new Mock<ITable<Forum>>();
            tableMock.Object.Attach(dummyForum);
            Mock<IDataContextWrapper> mock = new Mock<IDataContextWrapper>();
            mock.Setup(m => m.GetTable<Forum>()).Returns(tableMock.Object) ;

            //act
            ForumRepository repos = new ForumRepository(mock.Object);
            Forum resultForum = repos.GetForumById(1);

            //assert
            Assert.AreEqual(resultForum.tblForumID, 1);

其中论坛是一个自动生成的类。我想为表格设置论坛,这样当我在GetTable上做ContextWrapper时,我就会得到论坛的表格。我不知道Table.Attach是否会把论坛附加到桌面上。另外,当我运行测试时,上面写着

“要模拟的类型必须是接口、抽象类或非密封类”。

我搞错了吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-08-15 13:12:28

我看到你想做的事有几个问题。

  1. 发布的代码不编译。 IDataContextWrapper.GetTable返回Table<T>,因此不能将其设置为返回模拟的ITable<T>ITable不是Table,而是相反。这就引出了我的下一个观点:
  2. IDataContextWrapper.GetTable应该返回一个ITable<T>,而不是Table<T>。 这将允许您模拟返回结果,因为Table<T>密封的 (Moq不能模拟密封类,这可能就是您得到所提到的错误的原因)。它也是程序接口的好设计,而不是混凝土设计。
  3. 您不应该期望对Attach的调用会做任何事情 您试图在模拟的接口上调用一个方法,就像您期望它表现得好像有什么东西已经实现了一样。模拟的方法只执行您让他们做的事情,因此在本例中(使用松散行为),它将不会对该调用进行任何操作。相反,您应该设置您希望该表执行的操作,但这将导致我注意到:
  4. 您不能设置对Single的调用,因为它是一个扩展方法 Moq 不支持设置扩展方法,因为它们是静态方法。但是,您可以设置对GetEnumerator的调用,这也是Single所称的。不过,您需要成员,因为这正是Single真正要达到的目标。

因此,在解决了上面的第1点之后,您的测试最终应该如下所示:

代码语言:javascript
复制
[Test]
public void Can_Get_Forum_ById()
{
    // arrange
    Forum dummyForum = new Forum { tblForumID = 1 };
    IQueryable<Forum> forums = new List<Forum> { dummyForum }.AsQueryable();

    Mock<ITable<Forum>> tableMock = new Mock<ITable<Forum>>();
    tableMock.Setup(p => p.GetEnumerator()).Returns(forums.GetEnumerator());
    tableMock.Setup(r => r.Provider).Returns(forums.Provider);
    tableMock.Setup(r => r.ElementType).Returns(forums.ElementType);
    tableMock.Setup(r => r.Expression).Returns(forums.Expression);

    Mock<IDataContextWrapper> mock = new Mock<IDataContextWrapper>();
    mock.Setup(m => m.GetTable<Forum>()).Returns(tableMock.Object);

    // act
    ForumRepository repos = new ForumRepository(mock.Object);
    Forum resultForum = repos.GetForumById(1);

    // assert
    Assert.AreEqual(resultForum.tblForumID, 1);
}

请注意,这是一个好的,不是很好的测试。您可以将对Single的调用替换为对First的调用,它仍然会通过,但显然是错误的。您至少应该添加此测试的否定项,即如果Id不匹配,则不返回任何对象。

票数 3
EN

Stack Overflow用户

发布于 2014-08-14 18:05:57

试试像这样的东西

代码语言:javascript
复制
Forum dummyForum = new Forum() { tblForumID = 1};
            Mock<ITable> tableMock = new Mock<ITable>();
            tableMock.Object.Attach(dummyForum);
            Mock<IDataContextWrapper> contextMock = new Mock<IDataContextWrapper>();
            contextMock .Setup(m => m.GetTable<Forum>()).Returns((ITable<Forum>)tableMock.Object) ;

            //act
            ForumRepository repos = new ForumRepository(mock.Object);
            Forum resultForum = repos.GetForumById(1);

            //assert
            Assert.AreEqual(resultForum.tblForumID, 1);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25313411

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档