0

刚刚遇到一个问题。我正在尝试准备好 wcf 服务 unittest 或更好地使用 unittest 测试所有代码。

Atm 不可能因为我已经连接到每次使用的 crm 2011 服务器。
所以我用接口替换了它。但我想像你使用它一样对 WCF 进行单元测试。
现在我的想法是创建一个公共方法并提供一个虚假的连接。

现在我的问题是是否可以调用此方法(例如:ConnectionHandler),即使它不在界面中?

这看起来像这样:

public interface IWCF
{
    [OperationContract]
    bool method1();

    [OperationContract]
    bool method2();
}

public class WCF:  IWCF
{

    public bool method1(){
    ...
    }

    public bool method2(){
    ...
    }

    private connection connectionHandler;
    public connection ConnectionHandler(Iconnection con){
        if(con != null){
            connectionHandler = con;
        } else {
            connectionHandler = takedefault;
        }
    }
}

编辑
啊,我忘了告诉这一点:我实际上考虑到了安全性,我不希望任何人都可以将不同的连接传递给服务器,仅用于单元测试目的。

4

2 回答 2

1

可以调用此方法,您可以将接口强制转换为具体对象。但这会损害调用代码,它不应该知道您的服务的实现细节。

我建议在您的情况下使用构造函数注入,因此您的服务实现如下所示:

 public interface IWCF
{
    [OperationContract]
    bool method1();

    [OperationContract]
    bool method2();
}

public class WCF:  IWCF
{
    private connection connectionHandler;

    public WCF(Iconnection con)
    {
         if(con != null){
            connectionHandler = con;
        } else {
            connectionHandler = takedefault;
        }
    }

    public bool method1(){
    ...
    }

    public bool method2(){
    ...
    }



}

在这种情况下,如果您在客户端上也使用构造函数注入,客户端代码将不知道服务实现的细节

于 2013-09-25T08:45:32.773 回答
0

任何设计良好的代码的重要特征之一是您明确向客户公开的功能。这成为面向服务的应用程序的一个关键特性,因为您以标准化的方式公开您的功能供外部客户端使用。

调用不属于接口的方法原则上是不好的,因为您现在正在对实现而不是接口进行编程。令人高兴的是,WCF 知道这一点,并且不会让您使用不在接口上的方法,因为它没有用 OperationContract属性修饰。

关于您的代码-我不确定您到底要实现什么-拥有一个客户端集(我假设是)像数据库连接这样的东西让我有点不安(首先这意味着您的服务是持有一些违反服务无状态原则的状态)。这并不意味着您所做的事情一定是错误的,但是您应该发现在设计良好的应用程序中很少需要违反这一点。

也就是说,如果您想向不同的客户端公开不同的功能区域,正确的方法是在您的服务上公开代表不同合约的端点:

[ServiceContract]
public interface IWCF
{
    [OperationContract]
    bool method1();

    [OperationContract]
    bool method2();
}

 [ServiceContract]
public interface IConnectionWCF
 {
     [OperationContract]
     bool SetConnection(string connection);
 }

 public class WCF : IWCF, IConnectionWCF
{
     public bool method1()
     {
        ...
     }

     public bool method2()
     {
        ...
     }

     public bool SetConnection(string connection)
     {
         ...
     }
}

您还需要注意,WCF 服务接收到的所有内容都必须首先由客户端序列化,通过网络发送,然后在服务器上反序列化。您在这里非常处理具体的类 - 而不是抽象。Iconnection在面向服务的环境中,将接口(例如)作为参数传递给服务调用实际上没有任何意义。

关于单元测试——请记住,从根本上讲,该类WCF只是一个普通的旧类。您可以在隔离它是 WCF 服务这一事实的情况下对此类进行单元测试。无论如何,您都不应该在单元测试中设置任何服务托管功能 - 您想检查您编写的代码是否正确 - WCF 堆栈已经过 Microsoft 测试。

编辑

作为对您的评论的回应,正如此处所建议的,您应该在实例化类时使用构造函数注入来设置连接对象。这就提出了如何控制 WCF 服务的实例化的问题。您需要实现IInstanceProvider,或者更详细的实现见这里。这样,当您的服务托管在 WCF 中时,您可以使用IInstanceProvider,当您进行测试时,您只需将假连接对象传递给构造函数。

编辑

为了澄清,这个类的单元测试类似于:

[TestClass]
public class UnitTests
{
    [TestMethod]
    public void Test()
    {
        Iconnection connection = new FakeConnection();
        WCF classUnderTest = new WCF(connection);

        //Run test logic
    }
}
于 2013-09-25T10:13:42.843 回答