Тестирование Spring.NET Injected Membership Provider

Мне нравится гибкость внедрения провайдера членства, но я ломаю голову, пытаясь пройти интеграционные тесты. Моя версия веб-приложения без проблем внедряет поставщика членства в мой сервисный уровень, но я не могу настроить его/работать должным образом в моей версии приложения для модульного/интеграционного тестирования. Вот как у меня все настроено для поставщика членства.

App.config:

<configuration>

  <configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
    </sectionGroup>
  </configSections>

  <spring>
    <context>
      <resource uri="assembly://App.UI/App.UI/auth-config.xml"/>
      <resource uri="assembly://App.UI/App.UI/core-config.xml"/>
    </context>
  </spring>

  <connectionStrings>
    <add name="ApplicationServices" providerName="System.Data.SqlClient"
         connectionString="server=localhost;database=aspnetdb;User ID=AppWebUser;Password=p@ssw0rd" />
    <add name="appDb" providerName="System.Data.SqlClient"
         connectionString="server=localhost;database=app;Persist Security Info=False;User ID=AppWebUser;Password=p@ssw0rd"/>
    <add name="test_appDb" providerName="System.Data.SqlClient"
              connectionString="server=localhost;database=app_test;Persist Security Info=False;User ID=AppWebUser;Password=p@ssw0rd"/>
  </connectionStrings>

  <system.web>
    <membership defaultProvider="AppSqlMembershipProvider">
      <providers>
        <clear/>
        <add connectionStringName="" name="AppSqlMembershipProvider" type="Spring.Web.Providers.MembershipProviderAdapter, Spring.Web"
             enablePasswordRetrieval="false"
             enablePasswordReset="true"
             requiresQuestionAndAnswer="false"
             requiresUniqueEmail="false"
             passwordFormat="Hashed"
             maxInvalidPasswordAttempts="5"
             minRequiredPasswordLength="7"
             minRequiredNonalphanumericCharacters="0"
             passwordAttemptWindow="10"
             passwordStrengthRegularExpression=""/>
      </providers>
    </membership>

    <roleManager enabled="true" defaultProvider="AppSqlRoleProvider">
      <providers>
        <clear/>
        <add connectionStringName="" name="AppSqlRoleProvider" type="Spring.Web.Providers.RoleProviderAdapter, Spring.Web"/>
      </providers>
    </roleManager>

    <profile defaultProvider="AppSqlProfileProvider">
      <providers>
        <clear/>
        <add name="AppSqlProfileProvider" type="Spring.Web.Providers.ProfileProviderAdapter, Spring.Web" connectionStringName=""/>
      </providers>
      <properties>
        <add name="Greeting" type="String"/>
      </properties>
    </profile>
  </system.web>

</configuration>

auth-config.xml:

<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">

  <object id="AppSqlMembershipProvider" type="Spring.Web.Providers.ConfigurableSqlMembershipProvider">
    <property name="connectionStringName" value="ApplicationServices" />
    <property name="parameters">
      <name-values>
        <add key="description" value="membershipprovider description" />
      </name-values>
    </property>
  </object>

  <object id="AppSqlRoleProvider" type="Spring.Web.Providers.ConfigurableSqlRoleProvider">
    <property name="connectionStringName" value="ApplicationServices" />
    <property name="parameters">
      <name-values>
        <add key="description" value="roleprovider description" />
      </name-values>
    </property>
  </object>

  <object id="AppSqlProfileProvider" type="Spring.Web.Providers.ConfigurableSqlProfileProvider">
    <property name="connectionStringName" value="ApplicationServices" />
    <property name="parameters">
      <name-values>
        <add key="description" value="profileprovider description" />
      </name-values>
    </property>
  </object>

</objects>

Мой MembershipProvider настроен в core-config.xml:

<object id="AccountMembershipService" type="App.Core.Services.AccountMembershipService, App.Core.Services" >
  <constructor-arg name="provider" ref="AppSqlMembershipProvider"/>      <!-- see auth-config.xml for membership provider -->
</object>

Как я упоминал ранее, я могу внедрить Service без проблем в свое веб-приложение, но я не могу заставить мой тест работать правильно:

[TestFixture]
public class AccountMembershipServiceTest 
{
    protected IMembershipService AccountMembershipService { get; set; }   // properyt injected
    [Test]
    public void SanityCheck()
    {
        Assert.IsNotNull(this.AccountMembershipService);            
    }        
}

Но, увы.... провал:

------ Test started: Assembly: App.Tests.dll ------

Test 'App.Tests.IntegrationTesting.AccountMembershipServiceTest.SanityCheck' failed: 
  Expected: not null
  But was:  null
    Integration\AccountMembershipServiceTest.cs(23,0): at App.Tests.IntegrationTesting.AccountMembershipServiceTest.SanityCheck()

0 passed, 1 failed, 0 skipped, took 1.80 seconds (NUnit 2.5.5).

У кого-нибудь еще есть такая же проблема или он тоже решил это с помощью Spring.NET?

ПРИМЕЧАНИЕ. Все мои другие настроенные объекты в моем приложении для модульного/интеграционного тестирования работают, только мой провайдер членства вызывает проблемы.




Ответы (1)


Я думаю, что проблема в вашем тестовом коде, а не в конфигурации членства или конфигурации контекста Spring.NET.

Чтобы использовать тесты с внедрением зависимостей Spring.NET твой тест

  • должен наследоваться от одного из базовых классов теста Spring.NET
  • должны иметь общедоступные свойства для внедрения (с использованием автоматического подключения по типу по умолчанию) - если ваше свойство защищено, оно будет нулевым, и вы получите неудачный результат теста из своего вопроса.
  • следует указать расположение конфигурации

Например:

[TestFixture]
public class AccountMembershipServiceTest : 
             AbstractDependencyInjectionSpringContextTests
{
  // public properties will be auto-wired by type:
  public IMembershipService AccountMembershipService { get; set; }

  protected override string[] ConfigLocations { ... }
}

Если вы хотите использовать защищенные поля для зависимости, то вам следует использовать защищенные поля, а не свойства, и установить PopulateProtectedVariables = true в конструкторе тестов:

[TestFixture]
public class AccountMembershipServiceTest :
             AbstractDependencyInjectionSpringContextTests
{
    public AccountMembershipServiceTest ()
    {
        PopulateProtectedVariables = true;
    }

    // protected fields will be looked up in the container by field name:
    protected IMembershipService AccountMembershipService;


    protected override string[] ConfigLocations { ... }
}

Я подозреваю, что ваша конфигурация членства на самом деле правильная:

person Marijn    schedule 25.01.2012
comment
Возможно, я скрывал слишком много деталей в своем тесте. Мой «AccountMembershipServiceTest» фактически наследуется от другого класса, который наследуется от «AbstractTransactionalDbProviderSpringContextTests». Я пробовал «AbstractDependencyInjectionSpringContextTests» и «AbstractSpringContextTests»… до сих пор нет костей. Я вижу настроенные объекты, но не внедряю. На выходных займусь этим поглубже. - person Will Sams; 27.01.2012
comment
Не уверен, почему я принудительно защитил там. Сделал их общедоступными и установил автоматическое обнаружение. - person Will Sams; 27.01.2012
comment
Отлично у вас получилось. Я не уверен, почему вам нужно вручную настроить автообнаружение для автообнаружения. Кстати, в комментариях вы можете использовать обратную кавычку (``) вместо одиночной кавычки ('), чтобы применить форматирование кода: «AbstractSpringContextTests» становится AbstractSpringContextTests. Это работает и в вопросах и ответах. - person Marijn; 27.01.2012
comment
Ах, спасибо! Что касается автоопределения, это не было частью исправления. Я поигрался с некоторыми атрибутами, но оставил их для автоопределения. - person Will Sams; 28.01.2012