15

这是一个艰难的问题,因为使用 Pex 和 Moles 的人并不多,我认为(尽管 Pex 是一个非常棒的产品 - 比任何其他单元测试工具都要好得多)

我有一个数据项目,它有一个非常简单的模型,只有一个实体(DBItem)。我还在DBRepository这个项目中编写了一个操作这个 EF 模型的代码。Repository 有一个称为GetItems()返回业务层项目列表 ( BLItem) 的方法,看起来与此类似(简化示例):

public IList<BLItem> GetItems()
{
    using (var ctx = new EFContext("name=MyWebConfigConnectionName"))
    {
        DateTime limit = DateTime.Today.AddDays(-10);
        IList<DBItem> result = ctx.Items.Where(i => i.Changed > limit).ToList();
        return result.ConvertAll(i => i.ToBusinessObject());
    }
}

所以现在我想为这个特定的方法创建一些单元测试。我正在使用Pex & Moles。我为我的 EF 对象上下文创建了痣和存根。

我想编写参数化的单元测试(我知道我首先编写了我的生产代码,但我必须这样做,因为我正在测试 Pex 和 Moles)来测试此方法是否返回有效的项目列表。

这是我的测试课:

[PexClass]
public class RepoTest
{
    [PexMethod]
    public void GetItemsTest(ObjectSet<DBItem> items)
    {
        MEFContext.ConstructorString = (@this, name) => {
             var mole = new SEFContext();
        };

        DBRepository repo = new DBRepository();
        IList<BLItem> result = repo.GetItems();

        IList<DBItem> manual = items.Where(i => i.Changed > DateTime.Today.AddDays(-10));

        if (result.Count != manual.Count)
        {
            throw new Exception();
        }
    }
}

然后我为这个特定的参数化单元测试运行Pex Explorations,但我得到一个错误path bounds exceeded。Pex 通过提供null给这个测试方法 (so items = null) 来开始这个测试。这是 Pex 正在运行的代码:

[Test]
[PexGeneratedBy(typeof(RepoTest))]
[Ignore("the test state was: path bounds exceeded")]
public void DBRepository_GetTasks22301()
{
    this.GetItemsTest((ObjectSet<DBItem>)null);
}

这是 Pex 提供的附加评论:

对于这些输入,测试用例运行时间过长,Pex 停止了分析。请注意:方法 Oblivious.Data.Test.Repositories.TaskRepositoryTest.b__0 被调用了 50 次;请检查代码是否陷入无限循环或递归。否则,单击“设置 MaxStack=200”,然后再次运行 Pex。

更新属性 [PexMethod(MaxStack = 200)]

问题

我这样做是否正确?我应该改用 EFContext 存根吗?我是否必须在测试方法中添加其他属性,以便 Moles 主机运行(我不确定现在是否可以)。我只运行 Pex & Moles。没有 VS 测试或 nUnit 或其他任何东西。

我想我应该对 Pex 设置一些限制,它应该为这个特定的测试方法提供多少项目。

4

3 回答 3

5

Moles 并非旨在测试应用程序中具有外部依赖关系的部分(例如文件访问、网络访问、数据库访问等)。相反,Moles 允许您模拟应用程序的这些部分,以便您可以对没有外部依赖项的部分进行真正的单元测试。

所以我认为你应该模拟你的 EF 对象和查询,例如,通过创建内存列表并让查询方法根据任何相关标准从这些列表中返回假数据。

于 2010-11-12T04:16:17.857 回答
0

您应该使用实体框架存储库模式: http: //www.codeproject.com/KB/database/ImplRepositoryPatternEF.aspx

于 2010-11-06T16:33:50.383 回答
0

我也刚刚开始掌握 pex ......我的问题围绕着我想要将它与 moq 一起使用;)

反正 ...

我有一些与您类似的方法也有同样的问题。当我增加最大值时,它们就消失了。大概 pex 对它已经充分探索了分支感到满意。我有一些方法,我也不得不增加代码合同验证的超时时间。

不过,您可能应该做的一件事是将所有依赖对象作为参数传递……即不要在方法中实例化 repo,而是将其传递进去。

您遇到的一个普遍问题是您在方法中实例化大对象。我在我的 DAL 类中做同样的事情,但是我不会尝试单独对它们进行单元测试。我建立数据集并使用它来测试我的数据访问代码。

我在我的业务逻辑和对象上使用 pex。

如果我要尝试测试我的 DAL 代码 ID,则必须使用 IOC 将数据上下文传递到方法中——这将使测试成为可能,因为您可以模拟数据上下文。

于 2010-10-04T12:20:32.053 回答