我有一个使用Redis协调服务器节点的Web应用程序。该应用程序具有集成测试,可以使用WebApp.Start
启动服务器实例,并使用HttpClient和SignalR .NET客户端对其进行调用。
我希望增强集成测试,多次调用WebApp.Start
来启动多个服务器实例,使用不同的端口号代替不同的主机地址。这应该很容易做到。我无法弄清楚的部分是如何从控制器访问每个实例对象。这些是诸如与Redis的连接和缓存字典之类的对象。传统上,它们是简单的静态字段。现在,我希望它们是使用Startup
对象实例化的实例字段。
我的问题是我应该如何创建每个Web应用程序的这些对象,以及如何从Web API和SignalR控制器访问它们?
简化示例:
[TestMethod]
public void IntegrationTest()
{
// Starts 3 server instances.
for (int port = 9000; port < 9003; ++port)
WebApp.Start("http://localhost:" + port);
// Validates SignalR events on 9000.
var hubConnection9000 = new HubConnection("http://localhost:9000");
hubConnection9000.CreateHubProxy("MyHub").On<MyMessage>(name, m => Assert.IsTrue(...));
hubConnection9000.Start().Wait();
// Sends a SignalR command to 9001. Causes an event on 9000.
var hubConnection9001 = new HubConnection("http://localhost:9001");
hubConnection9001.CreateHubProxy("MyHub").Invoke("DoIt").Wait();
// Sends a Web API request to 9002. Causes an event on 9000.
var httpClient9002 = new HttpClient { BaseAddress = new Uri("http://localhost:9002") };
httpClient9002.PostAsJsonAsync("api/My/NewRecord", "[]").Result.EnsureSuccessStatusCode();
}
// From Startup.Configuration(IAppBuilder app):
// Creates a per-web-application backplane object which communicates to other servers.
object addresses;
int customPort = app.Properties.TryGetValue("host.Addresses", out addresses) ? int.Parse((string)((List<IDictionary<string, object>>)addresses)[0]["port"], CultureInfo.InvariantCulture) : 0; // The custom port number if one was provided at startup; otherwise, 0.
var backplane = new Backplane(customPort);
new AppProperties(app.Properties).OnAppDisposing.Register(() => { backplane.Dispose(); });
public class MyController : ApiController
{
[HttpPost]
public void NewRecord(string[] items)
{
// I want to use Backplane. How do I get at it?
}
}
public class MyHub : Hub<IMy>
{
public void DoIt()
{
// I want to use Backplane. How do I get at it?
}
}
internal class Backplane
{
// A Redis object that is expensive to create and should be shared with the entire web application.
readonly StackExchange.Redis.ConnectionMultiplexer redis = StackExchange.Redis.ConnectionMultiplexer.Connect();
}