私はAutofacとOWINをゼロからビルドしたWebAPIプロジェクトで使用しています(VS2015で利用可能な完全なWebAPIテンプレートに加えて)。確かに私はこのようにするのが初めてです。ユニットテストプロジェクトでユニットテストでWebAPI2を使用しているRequestContext.PrincipalのAutofac DI
は、私はユニットテストの開始時にOWINスタートアップクラスを設定し、次のよう
WebApp.Start<Startup>("http://localhost:9000/")
スタートアップクラスは次のとおりです。
[assembly: OwinStartup(typeof(API.Specs.Startup))]
namespace API.Specs
{
public class Startup
{
public void Configuration(IAppBuilder appBuilder)
{
var config = new HttpConfiguration();
//config.Filters.Add(new AccessControlAttribute());
config.Services.Replace(typeof(IAssembliesResolver), new CustomAssembliesResolver());
config.Formatters.JsonFormatter.SerializerSettings = Serializer.Settings;
config.MapHttpAttributeRoutes();
// Autofac configuration
var builder = new ContainerBuilder();
// Unit of Work
var unitOfWork = new Mock<IUnitOfWork>();
builder.RegisterInstance(unitOfWork.Object).As<IUnitOfWork>();
// Principal
var principal = new Mock<IPrincipal>();
principal.Setup(p => p.IsInRole("admin")).Returns(true);
principal.SetupGet(p => p.Identity.Name).Returns('test.user');
principal.SetupGet(p => p.Identity.IsAuthenticated).Returns(true);
Thread.CurrentPrincipal = principal.Object;
if (HttpContext.Current != null)
{
HttpContext.Current.User = new GenericPrincipal(principal.Object.Identity, null);
}
builder.Register(c => principal).As<IPrincipal>();
.
.
.
// Set up dependencies for Controllers, Services & Repositories
.
.
.
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
appBuilder.UseWebApi(config);
}
private static void RegisterAssemblies<TModel, TController, TService, TRepoClass, TRepoInterface>(ref ContainerBuilder builder, ref Mock<IUnitOfWork> unitOfWork)
where TModel : class
where TRepoClass : class
where TService : class
{
RegisterController<TController>(ref builder);
var repositoryInstance = RegisterRepository<TRepoClass, TRepoInterface>(ref builder);
RegisterService<TService>(ref builder, ref unitOfWork, repositoryInstance);
}
private static void RegisterController<TController>(ref ContainerBuilder builder)
{
builder.RegisterApiControllers(typeof(TController).Assembly);
}
private static object RegisterRepository<TRepoClass, TRepoInterface>(ref ContainerBuilder builder)
where TRepoClass : class
{
var constructorArguments = new object[] { DataContexts.Instantiate };
var repositoryInstance = Activator.CreateInstance(typeof(TRepoClass), constructorArguments);
builder.RegisterInstance(repositoryInstance).As<TRepoInterface>();
return repositoryInstance;
}
private static void RegisterService<TService>(ref ContainerBuilder builder, ref Mock<IUnitOfWork> unitOfWork, object repositoryInstance)
where TService : class
{
var constructorArguments = new[] { repositoryInstance, unitOfWork.Object};
var serviceInstance = Activator.CreateInstance(typeof(TService), constructorArguments);
builder.RegisterAssemblyTypes(typeof(TService).Assembly)
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces().InstancePerRequest();
builder.RegisterInstance(serviceInstance);
}
}
}
サイドノート:理想的には私さまざまなユーザーをコントローラに渡すことができるように、テストの一環としてPrincipleを設定したいと思いますが、スタートアップクラスのCurrentPrincipal/Userの設定を絶対に維持する必要がある場合は、回避できます。
スタートアップクラスはDIを使用してコントローラにアクセスしてもうまく動作しますが、RequestContext.Principal
のプリンシパルは設定されません。常にnullです。次のように私は意図要求コンテキストを使用する方法は次のとおりです。
[HttpGet]
[Route("path/{testId}")]
[ResponseType(typeof(Test))]
public IHttpActionResult Get(string testId)
{
return Ok(_service.GetById(testId, RequestContext.Principal.Identity.Name));
}
は私も回避策として、私のコントローラのコンストラクタに嘲笑主要なクラスを注入しようとした - 一般的な方法で表示されているように私は、同じ方法を使用しましたDIを使用して私のサービスをセットアップします。繰り返しますが、私はコンストラクタにnullしかありません。
この時点で私はこの問題で約1日座っていて、私の髪を引き出しています。どんな助けもありがとう。前もって感謝します。
こんにちはトラビス。後見では、あなたの解決策はかなり明白です。とてもうまく説明してくれてありがとう。今すぐあなたに戻ってくれたことを謝罪しました。私は回避策を使ってプロジェクトを進めなければなりませんでした。 – Ebbs