2

我正在尝试使用 Sqlite 为 ServiceStack 服务编写单元测试。由于 Sqlite 不支持存储过程,我创建了“ServiceCommand”类型的公共属性,该属性将命令文本和命令类型作为输入。默认情况下,它被配置为运行存储过程,并且在编写单元测试用例时,我在调用如下方法之前将 SelectCommand 属性重新分配给针对 sqlite 的 sql 查询Any()。所有测试用例都可以正常工作。

var request = new CustomerRequest() { name = "alfki"  };
var service = new CustomerService(InMemoryTestDatabase.OpenDbConnection());
service.SelectCommand = new ServiceCommand() { SQL = "SELECT * FROM customers where customerid = {0}" };
var result = service.Any(request);

但是根据这个线程,在解析引用时,IOC 将 CustomerService 的公共属性设置为 null,因此 SelectCommand 在Any()方法中为 null,从而导致对象引用错误。通过将属性设置为受保护、私有、内部或静态,我将无法运行单元测试。

public class CustomerService : Service
{
  private readonly IDbConnection _dbConnection;
  public ServiceCommand SelectCommand {get;set;}

  public CustomerService(IDBConnection dbConnection)
  {        
         _dbConnection = dbConnection;  //injected successfully
         SelectCommand =  new ServiceCommand(){ SQL = "sp_getcustomers",
            CommandType = CommandType.StoredProcedure};          
  }

  public Customer Any(CustomerRequest request)
  {
        //Select command is not accessible here.

  }
}


[Route("/customers")]
public class CustomerRequest
{
    public string name { get; set; }
}

服务命令

public class ServiceCommand
{
    public string SQL { get; set; }        
    public CommandType CommandType { get; set; }

    public ServiceCommand()
    {
        CommandType = CommandType.Text;
    }
}

为了能够同时运行测试用例和服务,我修改Any()了方法来实例化 ServiceCommand(如果它为空)。我想知道这是要走的路还是更好的选择。

public class CustomerService : Service
{
  private readonly IDbConnection _dbConnection; // injected successfully
  public ServiceCommand SelectCommand {get;set;}

  public CustomerService(IDBConnection dbConnection)
  {        
         _dbConnection = dbConnection;  //injected successfully         
  }

  public Customer Any(CustomerRequest request)
  {
        SelectCommand = SelectCommand ?? new ServiceCommand() { SQL = "sp_getCustomers",CommandType = CommandType.StoredProcedure };

  }
}
4

1 回答 1

1

由于ServiceStack服务将为所有公共属性注入已注册的 IOC 属性,因此它将覆盖您在构造函数中设置的值,因此您不能在不将其注册到 IOC 的情况下将其设为公共属性,因为它将被覆盖为 null。

鉴于此,一些可能的选择是:

使其成为公共领域

public class CustomerService : Service
{
    public ServiceCommand SelectCommand = new ServiceCommand { 
       SQL = "sp_getcustomers", 
       CommandType = CommandType.StoredProcedure };
    ...
}

使用 setter 注入只读属性

service.SetSelectCommand(
  new ServiceCommand { SQL = "SELECT * FROM customers where customerid = {0}" });

在您的 IOC 中注册并在您的构造函数中指定它

container.Register(new ServiceCommand { 
   SQL = "sp_getcustomers", 
   CommandType = CommandType.StoredProcedure });

并将构造函数更改为:

public CustomerService(IDBConnection dbConnection, ServiceCommand serviceCommand)
{        
    _dbConnection = dbConnection; 
    _serviceCommand = serviceCommand;    
}
于 2013-04-01T19:36:25.923 回答