我是 Moq 新手,刚刚开始一个已经在开发的项目。我负责设置单元测试。 DatabaseFactory 有一个使用 EnterpriseLibrary 的自定义类,如下所示:
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 类型的另一个类):
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 的新实例,并从那里使用它。然而,这使得该类无法测试,因为我无法阻止它实际访问数据库。因此,我采用了依赖注入(inject),并将数据库传入。
现在,我陷入了困境,因为无法模拟数据库来测试 GetNotifications。我想知道我是否把事情过于复杂化了,或者我是否遗漏了一些东西。我这样做的方式正确吗,还是应该重新考虑如何设置?
编辑以添加更多信息*****
我真的不想测试数据库。我希望 Data.Notifications 类(上面)返回 ResultData 的实例,但这就是我真正想要测试的全部。如果我上升到业务层,我会得到以下内容:
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 类创建了它 - 但话又说回来,如果我这样保留它,我就忍不住要点击数据库来测试这个业务层对象。我修改了所有代码以传递数据库(它创建了网络的基本页面),但现在我不确定下一步要做什么。我以为我只需要一个单元测试就可以解决这个问题,但显然,要么我错了,要么我在正确的道路上遇到了心理障碍。
最佳答案
如果其中的方法是虚拟的,您应该能够创建一个模拟数据库对象。如果不是,那么你就遇到了一些问题。
我不知道“数据库”是什么类型,但你有几个选择。
如果您拥有数据库的源代码,我建议提取接口(interface) IDatabase,而不是处理数据库类类型。这将消除一些复杂性并为您提供非常可测试的东西。
如果您无权访问 Database 类,您始终可以通过另一层抽象来解决此问题。在这种情况下,许多人使用包装数据访问层的存储库模式。一般来说,在这种情况下,大多数人将测试 Respository 类留给集成测试(没有任何隔离的测试),而不是单元测试。
以下是使用选项 #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);
}
我的数据集代码有点生疏,但希望这能为您提供总体思路。
关于c#-3.0 - MSTest 与 Moq - DAL 设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2180363/