我使用使用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。
编辑:我似乎在InternalServerError和MethodNotAllowed错误之间反弹 - 仅在使用自托管时。我已经确保我作为用户有权打开端口(Win7 +非管理员),但是结果加上我选择的端口似乎可以预测Get的功能。 “帖子”似乎也有类似的问题! : - (
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);
}
答案 0 :(得分:4)
当我更改方法签名以接受HttpRequestMessage请求而不是T本身时,做PUT或POST对我有用。