在每个单元测试中对 WCF 服务使用不同的终结点



我有一个表示WCF服务的类,该服务用作我想进行单元测试的类中的成员变量。 这将涉及编写许多场景,我遇到的问题是,多次构造类会导致除一个单元测试之外的所有单元测试都出现"URI 注册"错误。

任何单元测试都单独成功,但是如果我在同一测试运行中运行两个或多个测试,那么我就有问题了。

我的问题是,如何让单元测试在运行所有单元测试的标准测试运行中运行?

我的测试代码是这样开始的:

var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var serviceModel = ServiceModelSectionGroup.GetSectionGroup(config);
var services = serviceModel.Services;
var address = services.Services[serviceName].Endpoints[0].Address;
var addressParts = address.AbsoluteUri.Split('/');
var newAddress = string.Join("/", addressParts.Take(addressParts.Length - 1));
newAddress = newAddress + "/" + Guid.NewGuid().ToString();
services.Services[0].Endpoints[0].Address = new System.Uri(newAddress);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(serviceModel.Name);
var callRouter = new CallRouter();
var sut = new Callmanager(callRouter);

其中我的类有一个构造函数:

public CallManager(ICallRouter callRouter)
{
    if (callRouter == null)
        throw new ArgumentNullException(nameof(callRouter));
    this.callRouter = callRouter;
    this.callRouter.StartCallHandler += CallStarted;
    this.callRouter.EndCallHandler += CallEnded;
    hostCallManager = new System.ServiceModel.ServiceHost(callRouter);
    hostCallManager.Open();
}

在我的应用程序配置中,我有:

<system.serviceModel>    
<services>
  <service name="CallRouter">
    <endpoint address="net.tcp://localhost:8011/Service" binding="netTcpBinding" contract="ICallServiceRouter" />
  </service>
</services>

所以我正在尝试的是动态为每个单元测试生成一个新端点(通过更改地址以包含 guid),但这似乎不起作用,因为当我在同一测试运行中运行所有单元测试时,生成的每个 CallRouter 实例都使用相同的地址(每次运行时地址都不同, 所以修正正在工作),就好像正在使用 app.config 的最后一个修正一样。

这是有道理的,因为它们都从同一个进程运行,并且并行运行,因此文件写入正在发生,并且由于运气不好,配置在加载之前被修改了多次,但是当它被加载时,CallRouter 的所有实例都会获得相同的端点值。

有没有办法使System.ServiceModel构造函数使用的配置对于同一会话中的每个单元测试都不同?

您不必更改配置文件。相反,请创建服务实例并在测试中以编程方式配置它们,如下所示:

hostCallManager = new ServiceHost(callRouter, new Uri("Unique URI for your test"));
hostCallManager.AddServiceEndpoint(typeof(ICallServiceRouter), new NetTcpBinding(), string.Empty);
hostCallManager.Open();

最新更新