我已经使用使用put谓词的WCF WebAPI构建了一个HTTP驱动的API。当托管在IIS Express上托管的MVC3项目内部时,一切都按设计工作。
然而,当我进行单元测试时,我偶尔会想测试传输方面,而不仅仅是针对我自己的资源。我的单元测试以405-MethodNotAllowed失败。同样,IIS中托管的服务完全相同(我在配置文件中启用了PUT和DELETE谓词)。
如何让测试中使用的"自托管"服务也接受这些动词
几乎相同的"get"测试有效,所以我不认为以下概念有错。。有希望地
[Test]
public void PutNewMachine()
{
// Create new record to add
var machine = new Machine
{
ID = 1,
Name = "One",
Description = "Machine #1",
Location = 1
};
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage(
HttpMethod.Put,
HOST + "/1"))
{
request.Content = new ObjectContent<Machine>(machine);
using (var response = client.Send(request))
{
Assert.AreEqual(
HttpStatusCode.Created,
response.StatusCode,
"New record put should have been acknowledged "
+ "with a status code of 'Created'");
}
}
}
}
在测试的设置中,我使用以下Autofac代码准备终点(同样适用于"Get"):
var builder = new ContainerBuilder();
builder
.Register(c => new FakeDatabase())
.As<IDatabase>()
.SingleInstance();
builder
.Register(c => new GenericRepository<Machine>(c.Resolve<IDatabase>()))
.As<IResourceRepository<Machine>>();
builder
.Register(c => new MachineService(c.Resolve<IResourceRepository<Machine>>()))
.As<MachineService>();
Container = builder.Build();
Scope = Container.BeginLifetimeScope();
host = new HttpServiceHost(typeof(MachineService), HOST);
host.AddDependencyInjectionBehavior<MachineService>(Container);
host.Open();
我的服务在以下界面中定义:
[ServiceContract]
public interface IResourceService<in TKey, TResource>
{
[WebGet(UriTemplate = "{key}")]
TResource Get(TKey key);
[WebInvoke(Method = "PUT", UriTemplate = "{key}")]
TResource Put(TKey key, TResource resource);
[WebInvoke(Method = "POST")]
TResource Post(TResource resource);
[WebInvoke(Method = "DELETE", UriTemplate = "{key}")]
void Delete(TKey key);
}
因此,例如,如果我有一个MachineService,它会实现接口(class MachineService : IResourceService<string, Machine>
和... : IResourceService<int, Machine>
都已经过测试——Get=OK,Put=Nothing。
EDIT:我似乎在InternalServerError和MethodNotAllowed错误之间来回切换——只有在使用自托管时。我已经确保,作为一名用户,我有权打开端口(Win7+非管理员),但结果加上我选择的端口似乎可以预测Get的功能。"Post"似乎也有类似的问题!:-(
EDIT2:界面现在已更改为可用界面!
[ServiceContract]
public interface IResourceService<in TKey, TResource>
{
[WebGet(UriTemplate = "{key}")]
TResource Get(TKey key);
[WebInvoke(Method = "PUT", UriTemplate = "{key}")]
TResource Put(HttpRequestMessage<TResource> resourceRequest, TKey key);
[WebInvoke(Method = "POST", UriTemplate = "{key}")]
TResource Post(HttpRequestMessage<TResource> resourceRequest, TKey key);
[WebInvoke(Method = "DELETE", UriTemplate = "{key}")]
void Delete(TKey key);
}
当我更改方法签名以接受HttpRequestMessage请求而不是T本身时,执行PUT或POST对我有效。