模拟使用Enterprise Library返回IDataReader的DataAccess方法

时间:2017-11-13 22:09:45

标签: c# unit-testing moq

我被赋予了重写Api和相应单元测试的任务。我对单元测试仍然很陌生,所以我很难为使用Enterprise Library的数据访问类编写测试代码。这是代码:

df = structure(list(A = c("food", "food", "food", "food", "car", "car", 
"car", "car"), B = c("fruit", "fruit", "drink", "fruit", "suv", 
"sedan", "suv", "sedan"), C = c("apple", "", "", "", "ford", 
"bmw", "", "")), .Names = c("A", "B", "C"), class = "data.frame", row.names = c(NA, 
-8L))

以下是IDataAccess接口:

namespace TOS_Landside_BL.Classes {
  using System.Collections.Generic;
  using System.Data;
  using System.Data.Common;
  using Microsoft.Practices.EnterpriseLibrary.Data;
  using Interfaces;

  public class DataAccess : IDataAccess {
    private readonly Database yasDB;

    public DataAccess () {
      DatabaseProviderFactory factory = new DatabaseProviderFactory ();
      DatabaseFactory.SetDatabaseProviderFactory (factory, false);
      yasDB = factory.Create ("AutomationDB");
    }

    // caller is responsible for closing the reader.
    public IDataReader ExecuteReaderForStoredProcedure (string cmdName, List<DbParameter> parameters = null) {
      DbCommand cmd = yasDB.GetStoredProcCommand (cmdName);
      if (parameters != null)
        cmd.Parameters.AddRange (parameters.ToArray ());

      return yasDB.ExecuteReader (cmd);
    }

    public IDataReader ExecuteReaderForSqlStringCommand (string cmdScript, List <DbParameter> parameters = null) {
      DbCommand cmd = yasDB.GetSqlStringCommand (cmdScript);
      if (parameters != null) {
        cmd.Parameters.AddRange(parameters.ToArray());
      }

      return yasDB.ExecuteReader (cmd);
    }
  }
}

以下是我将如何称呼它的示例:

namespace TOS_Landside_BL.Interfaces {
  using System.Collections.Generic;
  using System.Data;
  using System.Data.Common;

  public interface IDataAccess {
    IDataReader ExecuteReaderForStoredProcedure (string cmdName, List<DbParameter> parameters = null);
    IDataReader ExecuteReaderForSqlStringCommand (string cmdScript, List <DbParameter> parameters = null);
  }
}

在我的测试类的SetUp方法中,我尝试了这个:

namespace TOS_Landside_BL.Data {
  using System;
  using System.Collections.Generic;
  using System.Data;
  using System.Data.Common;
  using System.Data.SqlClient;
  using System.Linq;
  using Classes;
  using Enums;
  using Factories;
  using Interfaces;

  public class LandsideTransactionDataProvider {
    private readonly IDataAccess _dataAccess;

    public LandsideTransactionDataProvider (IDataAccess dataAccess = null)  
    {
      _dataAccess = dataAccess ?? new DataAccess ();
    }

    public LandsideTransaction GetLandsideTransaction (string keyword, bool isKioskID = false)
    {
      var strCmd = isKioskID ? "proc_get_landside_transaction_by_kiosk_id" : "[LandSide].[GetLandsideTransactionDetail]";
      var parameters = new List <DbParameter> () {
        new SqlParameter ("@keyword", SqlDbType.NVarChar, 11) {Value = keyword}
      };

      using (var reader = _dataAccess.ExecuteReaderForStoredProcedure (strCmd, parameters)) {
        return reader.Read () ? reader.CreateLandSideTransaction () : null;
      }
    }
  }

但它不接受IDataReader或任何具体的数据读取器类。

请告知我做错了什么,任何建议真的值得赞赏。谢谢。

1 个答案:

答案 0 :(得分:0)

您可以为IDataReader创建模拟,并将其设置为测试。

var reader = new Mock<IDataReader>();
//..Setup the reader as expected for the test.
//Like reader.Read(), etc.

var dataAccess = new Mock<IDataAccess>();
dataAccess
    .Setup(_ => _.ExecuteReaderForStoredProcedure(It.IsAny<string>(), It.IsAny<List<DbParameter>>()))
    .Returns(reader.Object);//return mocked reader.