C# TDD首先是WCF服务类本身

C# TDD首先是WCF服务类本身,c#,wcf,unit-testing,tdd,C#,Wcf,Unit Testing,Tdd,因此,我开始为我想要创建的新WCF服务创建TDD测试。在TDD中,您创建测试,并开始将尚不存在的对象添加到测试中。我想测试的第一个对象是实例化后服务不为null 然后我说等等,你他妈的怎么能在WCF中做到这一点…服务扩展是.svc。是的,有一个.svc.cs,但主父级是.svc。在这一部分中,我看不到一种可以实现TDD的方法,在这一部分中,您有类似的东西,但它会创建一个.svc,而不仅仅是一个.cs: [TestMethod] public void UponInitializatio

因此,我开始为我想要创建的新WCF服务创建TDD测试。在TDD中,您创建测试,并开始将尚不存在的对象添加到测试中。我想测试的第一个对象是实例化后服务不为null

然后我说等等,你他妈的怎么能在WCF中做到这一点…服务扩展是.svc。是的,有一个.svc.cs,但主父级是.svc。在这一部分中,我看不到一种可以实现TDD的方法,在这一部分中,您有类似的东西,但它会创建一个.svc,而不仅仅是一个.cs:

 [TestMethod]
    public void UponInitialization_ServiceIsNotNull()
    {
        // Arrange
        // Act
        NyNewService service = new MyNewService();

        // Assert
        Assert.IsTrue(service != null);
    }
这是一个非常基本的必要的第一次测试,从一开始就尽可能简单地进行测试……这在任何TDD或XP团队进行TDD时都很常见


关于如何在我的测试中创建一个新的.svc,有什么想法吗?不是普通的.cs?

我首先要为不存在的WCF服务创建验收测试:

private Uri _baseAddress = new Uri("http://localhost:8713/service1");
private IService1 _client;

[SetUp]
public void Setup()
{
    var binding = new BasicHttpBinding();
    var endpoint = new EndpointAddress(_baseAddress);
    var factory = new ChannelFactory<IService1>(binding, endpoint);
    _client = factory.CreateChannel();
}

[TearDown]
public void TearDown()
{
    if (_client != null)
        ((ICommunicationObject)_client).Close();
}

[Test]
public void ShouldReturnSampleData()
{
    Assert.That(_client.GetData(42), Is.EqualTo("You entered: 42"));
}
测试现在可以编译了,但当然,它会出错

试图获取IService1的合同类型,但该类型不是 ServiceContract,也不继承ServiceContract

很好,这是因为我们应该用
[ServiceContract]
属性标记接口。我们添加此属性并再次运行测试:

此代理上不支持方法GetData,如果 方法未标记为OperationContractAttribute,或者 接口类型未标记为ServiceContractAttribute

好的,用所需属性标记我们的服务接口:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    string GetData(int value);
}
现在我们看到另一个错误(因为实际上没有任何东西在运行我们不存在的服务)

http://localhost:8713/service1
我可以接受这个消息。这通常是由地址不正确引起的 或SOAP操作。有关更多详细信息,请参阅InnerException(如果存在)

我们可以使用ServiceHost来运行我们的服务(此时我们需要创建服务类来编译测试):

您还需要按服务类实现IService1接口(否则测试将失败):


现在,为了实现GetData功能,我为Service1类创建了一些单元测试。通过这些测试后,您也将通过验收测试。就这样。您首先进行了测试,您的WCF服务已经完全准备好托管。

我认为构造函数要么抛出异常,要么返回非空值。所以,实际上这个测试什么都不做。svc只是一个托管问题,而不是实现细节。TDD主要是关于单元测试的,这意味着没有像文件系统或主机这样的外部依赖项。要测试.svc文件,您需要进行集成测试。@Sunny,不,您需要对服务类、服务本身进行TDD测试。通过TDD你可以创建类和方法,失败,让它们通过,等等@CoffeeAddict:true。你测试这个班级。不是.svc。为什么要测试创建服务实例?您应该测试您的实现/逻辑,而不是WCF(WCF承载详细信息,因此从服务层提取您的逻辑)。您不能为所有内容编写测试。这很好。我唯一想做的事情是模拟…而不是创建整个类来实现IService1,这将需要更少的代码来完成同样的事情(调用一个方法,告诉它发送什么和您期望返回什么..告诉它,这样在运行测试时它总是一致的)如果您有IService1,然后您想生成一个新的WCF.svc服务,那么如何使用ReSharper等实现这一点。您只能右键单击并创建.cs类。我希望能够使用TDD测试中的ReSharper为一个未实现的类创建WCF服务,或者甚至仅仅是一个服务本身,使用ReSharper的快捷方式。我的一个好朋友告诉我,有一些DI框架可以在没有接口的情况下进行模拟,而使用DI接口实际上是不必要的。例如,Java中的Spring不使用接口。是的,很多人使用接口,但最终也会使用太多的接口,以至于您的类不再遵守可靠的原则,因为您的类是单一责任的。与其继承大量接口,还不如让您的类承担单一的责任。ChannelFactory是您创建的自定义类吗?@CoffeeAddict不是,它是System.ServiceModel.ChannleFactory。我也不明白接口与SRP的关系。如果您的类遵循SRP,那么通常只有一个接口要继承。我在这里没有使用mock,因为这是验收测试,应该测试应用程序的整个堆栈。没有什么可以嘲笑的。这是单元测试(Service1类的测试),您应该在其中使用模拟,因为单元应该单独测试。关于ReSharper,我在这里帮不了你,我更喜欢ReSharper
[ServiceContract]
public interface IService1
{
    [OperationContract]
    string GetData(int value);
}
private ServiceHost _host;

[SetUp]
public void Setup()
{
    _host = new ServiceHost(typeof(Service1), _baseAddress);
    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    smb.HttpGetEnabled = true;
    smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
    _host.Description.Behaviors.Add(smb);
    _host.Open();

    // creating client as above
}

[TearDown]
public void TearDown()
{
    // closing client as above

    if (_host != null)
        _host.Close();
}
public class Service1 : IService1
{
    public string GetData(int value)
    {
        throw new NotImplementedException();
    }
}