1

我在测试中配置了一个 ServiceStack AppHostHttpListenerBase,目的是运行如下测试:

public class UserProfileBehaviours : BaseTest<UserProfileService>
{
    [Test]
    public void Can_access_secure_service()
    {
        var client = GetClientWithUserPassword();

        var result = ((IRestClient)client).Get(new Dto.View.Requests.UserProfileRequest
             {
                 Slug = "user"
             });

        result.Result.UserAccount.Username.Should().Be("user");
    }
}

我的 BaseTest 看起来像:

[TestFixture]
public class BaseTest<T>
{
    protected TestAppHostHttpListenerBase<T> AppHost;
    private const string ListeningOn = "http://localhost:82/";
    private const string UserName = "user";
    private const string Password = "p@55word";
    protected readonly Container Container;

    public BaseTest()
    {
        Container = new Funq.Container
        {
            Adapter = new WindsorContainerAdapter()
        };
    }

    [TestFixtureSetUp]
    public void OnTestFixtureSetUp()
    {
        AppHost = new TestAppHostHttpListenerBase<T>();

        AppHost.Init();

        AppHost.Start(ListeningOn);
    }

    [TestFixtureTearDown]
    public void OnTestFixtureTearDown()
    {
        AppHost.Dispose();
    }

    protected IServiceClient GetClient()
    {
        return new JsonServiceClient(ListeningOn);
    }

    protected IServiceClient GetClientWithUserPassword()
    {
        return new JsonServiceClient(ListeningOn)
        {
            UserName = UserName,
            Password = Password
        };
    }
}

然后是我的 WindsorContainerAdapter:

public static class CastleWindsor
{
    public static IWindsorContainer InstallFromAssemblies(this IWindsorContainer container, params string[] assemblyNames)
    {
        return container.Install(assemblyNames.Select(
            x => (IWindsorInstaller)new AssemblyInstaller(Assembly.Load(x), new InstallerFactory())).ToArray());
    }
}


public class WindsorContainerAdapter : IContainerAdapter, IDisposable
{
    private readonly IWindsorContainer _container;

    public WindsorContainerAdapter()
    {
        _container = new WindsorContainer("Windsor.config");
        _container.Register(Component.For<IWindsorContainer>().Instance(_container));
        _container.Install(FromAssembly.InThisApplication(), FromAssembly.InDirectory(new ApplicationAssemblyFilter())).InstallFromAssemblies("Web.Api");
        _container.Register(Classes.FromAssemblyNamed("Web.Api").BasedOn(typeof(IRepository<>)).LifestyleSingleton());
        _container.Register(Component.For<IEmailBuilder>().ImplementedBy<EmailBuilder>().LifeStyle.Singleton);
        _container.Register(Component.For<IEmailSender>().ImplementedBy<EmailSender>().LifeStyle.Singleton);
        _container.Register(Component.For<IEmailService>().ImplementedBy<EmailService>());
    }

    public T TryResolve<T>()
    {
        return !_container.Kernel.HasComponent(typeof(T)) ? default(T) :
            Resolve<T>();
    }

    public T Resolve<T>()
    {
        return _container.Resolve<T>();
    }

    public void Dispose()
    {
        _container.Dispose();
    }
}

最后是我的 TestAppHostHttpListener

public class TestAppHostHttpListenerBase<T> : AppHostHttpListenerBase
{
    public const string WebHostUrl = "http://localhost:82/";
    private InMemoryAuthRepository _userRep;
    private const string UserName = "user";
    private const string Password = "p@55word";
    public const string LoginUrl = "specialLoginPage.html";

    public TestAppHostHttpListenerBase()
        : base("Validation Tests", typeof(T).Assembly)
    {
    }

    public override void Configure(Container container)
    {

        var appSettings = new AppSettings();

        SetConfig(new EndpointHostConfig { WebHostUrl = WebHostUrl });

        Plugins.Add(new AuthFeature(
                        () =>
                        new AuthUserSession(),
                        new IAuthProvider[]
                            {
                                new BasicAuthProvider(),
                                new CredentialsAuthProvider(),
                                new TwitterAuthProvider(appSettings),
                                new FacebookAuthProvider(appSettings)
                            }, "~/" + LoginUrl));

        container.Register<ICacheClient>(new MemoryCacheClient());
        _userRep = new InMemoryAuthRepository();
        container.Register<IUserAuthRepository>(_userRep);
        CreateUser(1, UserName, null, Password, new List<string> { "TheRole" }, new List<string> { "ThePermission" });
    }

    private void CreateUser(int id, string username, string email, string password, List<string> roles = null, List<string> permissions = null)
    {
        string hash;
        string salt;
        new SaltedHash().GetHashAndSaltString(password, out hash, out salt);

        if (_userRep.GetUserAuthByUserName(username) == null)
        {
            _userRep.CreateUserAuth(new UserAuth
            {
                Id = id,
                DisplayName = "DisplayName",
                Email = email ?? "as@if{0}.com".Fmt(id),
                UserName = username,
                FirstName = "FirstName",
                LastName = "LastName",
                PasswordHash = hash,
                Salt = salt,
                Roles = roles,
                Permissions = permissions
            }, password);
        }
    }
}

在配置容器时,我可以看到有一个组件UserAccountRepository- 如果该组件是UserProfileService客户端的依赖项,则会收到一个异常,指出无法解决自动装配的依赖项。我不明白的是在哪里AppHostHttpListenerBase得到它的容器?

我的温莎适配器从未被要求Resolve存储库的组件。

我怎样才能给AppHostHttpListenerBase容器以便它可以解决这些依赖关系?还是我需要以另一种方式配置它?

4

1 回答 1

1

尝试将容器适配器设置在TestAppHostHttpListenerBase.Configure方法的顶部,而不是在您的BaseTest类中:

public override void Configure(Container container)
{
    container.Adapter = new WindsorContainerAdapter();
    ...
}

Container赋予该方法的对象是TestAppHostHttpListenerBase.Configure在 TestAppHostHttpListenerBase 的基本构造函数中创建的;您无法直接控制它的创建。这是您需要使用适配器等自定义的容器实例。

如果您还需要在您的UserProfileBehaviours或其他单元测试类中使用相同的 IoC 容器,我认为您可以通过静态属性引用它,并消除在构造函数EndpointHost.Container中创建的额外容器实例。BaseTest如上所述,容器对象将在您将 AppHost 对象实例化为OnTestFixtureSetUp.

于 2013-10-10T20:30:49.647 回答