带有Moq的MSTest-DAL设置 [英] MSTest with Moq - DAL setup

查看:148
本文介绍了带有Moq的MSTest-DAL设置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Moq的新手,刚开始一个已经在开发中的项目.我负责设置单元测试.有一个使用EnterpriseLibrary的DatabaseFactory自定义类,如下所示:

I'm new to Moq, and just started on a project that's already in development. I'm responsible for setting up unit testing. There's a custom class for the DatabaseFactory that uses EnterpriseLibrary and looks like this:

public Database CreateCommonDatabase()
{
  return CreateDatabaseInstance(string.Empty);
}

private static Database CreateDatabaseInstance(string foo)
{
  var database = clientCode == string.Empty
      ? DatabaseFactory.CreateDatabase("COMMON")
      : new OracleDatabase(new ClientConnections().GetConnectionString(foo)));
  return database;
}

现在,这是使用的地方(ResultData是DataSet类型的另一个类):

Now, here's where that gets used (ResultData is another class of the type DataSet):

public ResultData GetNotifications(string foo, string foo2, Database database)
{
    var errMsg = string.Empty;
    var retval = 0;
    var ds = new DataSet();

    var sqlClause =
    @"[Some SELECT statement here that uses foo]";

    DbCommand cm = database.GetSqlStringCommand(sqlClause);
    cm.CommandType = CommandType.Text;

    // Add Parameters
    if (userSeq != string.Empty)
    {
      database.AddInParameter(cm, ":foo2", DbType.String, foo2);
    }

    try
    {
      ds = database.ExecuteDataSet(cm);
    }
      catch (Exception ex)
    {
      retval = -99;
      errMsg = ex.Message;
    }

    return new ResultData(ds, retval, errMsg);
}

现在,最初,数据库没有作为参数传递,但是该方法是使用CreateCommonDatabase方法创建DatabaseFactory的新实例,然后从那里使用它.但是,这使该类无法测试,因为我无法阻止它实际访问数据库.因此,我进行了依赖注入,并传入了数据库.

Now, originally, the Database wasn't passed in as a parameter, but the method was creating a new instance of the DatabaseFactory using the CreateCommonDatabase method, and using it from there. However, that leaves the class untestable because I can't keep it from actually hitting the database. So, I went with Dependency Injection, and pass the Database in.

现在,我被困住了,因为无法模拟数据库来测试GetNotifications.我想知道我是否在使事情变得过于复杂,或者我是否缺少某些东西.我是用正确的方式做的,还是应该重新考虑如何进行设置?

Now, I'm stuck, because there's no way to mock Database in order to test GetNotifications. I'm wondering if I'm overly complicating things, or if I'm missing something. Am I doing this the right way, or should I be rethinking how I've got this set up?

编辑以添加更多信息*****

Edit to add more info*****

我真的不想测试数据库.我想要Data.Notifications类(上面)返回ResultData的实例,但这就是我真正想要测试的.如果我要升级到业务层,则有以下内容:

I really don't want to test the database. I want the Data.Notifications class (above) to return an instance of ResultData, but that's all I really want to test. If I go a level up, to the Business layer, I have this:

public DataSet GetNotifications(string foo, string foo1, out int returnValue, out string errorMessage, Database database)
{
    ResultData rd = new data.Notifications().GetNotifications(foo, foo1, database);

    returnValue = rd.ResultValue;
    errorMessage = rd.ErrorMessage;

    return rd.DataReturned;
}

因此,最初,数据库是没有传入的,而是由Data.Notifications类创建的-但是,如果我以这种方式离开数据库,那么我又不由自主地选择了数据库来测试该业务图层对象.我修改了所有代码以传递数据库(这将在Web的基础"页面中创建),但是现在我不确定下一步该怎么做.我以为我离解决这个问题还差一个单元测试,但是显然,我错了,或者我在通往正确道路上遇到了障碍.

So, originally, the database wasn't passed in, it was the Data.Notifications class that created it - but then again, if I left it that way, I couldn't help but hit the database to test this Business layer object. I modified all of the code to pass the Database in (which gets created a the web's Base page), but now I'm just not certain what to do next. I thought I was one unit test away from having this resolved, but apparently, either I'm wrong or I've got a mental roadblock to the right path.

推荐答案

如果其中的方法是虚拟的,则应该能够创建模拟数据库对象.如果不是,那么您会遇到一些问题.

You should be able to create a mock Database object if the methods in it are virtual. If they are not, then you have a little bit of a problem.

我不知道数据库"是什么类型,但是您有几个选择.

I don't know what type "Database" is, but you have a few options.

  1. 如果您拥有数据库的源代码,我建议您提取接口IDatabase,而不是处理Database类类型.这将消除一些复杂性,并为您提供一些可测试的东西.

  1. If you own the source code to Database, I would recommend extracting an interface IDatabase, rather than dealing with a Database class type. This will eliminate some complexity and give you something extremely testable.

如果您无权访问Database类,则始终可以使用另一层抽象来解决此问题.在这种情况下,许多人使用存储库模式包装数据访问层.一般来说,在这种情况下,大多数人将测试存储库类留给集成测试(没有任何隔离的测试),而不是单元测试.

If you don't have access to the Database class, you can always solve this with another layer of abstraction. Many people in this case use a Repository pattern that wraps the data access layer. Generally speaking in this case, most people leave testing Respository classes to integration tests (tests without any isolation), rather than unit tests.

以下是使用选项#1设置测试的方式:

Here's how you'd setup your test using option #1:

[TestMethod]
public void GetNotifications_PassedNullFoo_ReturnsData()
{
     //Arrange
     Mock<IDatabase> mockDB = new Mock<IDatabase>();
     mockDB.Setup(db => db.ExecuteDataSet()).Returns(new DataSet() ... );

     //Act
     FooClass target = new fooClass();
     var result = target.GetNotifications(null, "Foo2", mockDB.Object);

     //Assert
     Assert.IsTrue(result.DataSet.Rows.Count > 0);
}

我的数据集代码有些生疏,但是希望这能给您大致的思路.

My dataset code is a little rusty, but hopefully this gives you the general idea.

这篇关于带有Moq的MSTest-DAL设置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆