請求scoped豆春季試験
-
18-09-2019 - |
質問
ようになったのは使用の請求scoped豆私のアプリです。使っていJUnit4試験をします。いものを作ろうという試みの一試験のようになります:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/TestScopedBeans-context.xml" })
public class TestScopedBeans {
protected final static Logger logger = Logger
.getLogger(TestScopedBeans.class);
@Resource
private Object tObj;
@Test
public void testBean() {
logger.debug(tObj);
}
@Test
public void testBean2() {
logger.debug(tObj);
}
以下のbean定義:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="java.lang.Object" id="tObj" scope="request" />
</beans>
および取得します:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gov.nasa.arc.cx.sor.query.TestScopedBeans': Injection of resource fields failed; nested exception is java.lang.IllegalStateException: No Scope registered for scope 'request'
<...SNIP...>
Caused by: java.lang.IllegalStateException: No Scope registered for scope 'request'
私はこのブログを見ていると役に立:http://www.javathinking.com/2009/06/no-scope-registered-for-scope-request_5.html
もっ AbstractDependencyInjectionSpringcontexttests るよう推奨されていません春3.0です。思春2.5この時期にもかになりにくいものにスイッチこのメソッドを使用AbstractJUnit4SpringContextTests としてのドキュメントの提案(okのドキュメントへのリンク3.8版のものを使用してい4.4).ように変更したい 試験の延長AbstractJUnit4SpringContextTests...同じメッセージ。同じ問題です。現在のprepareTestInstance()メソッドをしたい をオーバーライドが定義されていない。ゃい方registerScope電話か...いについて TestExecutionListeners ると考えていくのならいいを受け継ぐ春のパッケージ構造です。なので 私は、試験:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/TestScopedBeans-context.xml" })
@TestExecutionListeners({})
public class TestScopedBeans {
想いをカスタムリスナーだったのです。本当にうまくいきます。素晴らしいですけど、なぜですか?んが、株式リスナー 登録請求の範囲又はセッションの範囲は、なぜでしょうか。あの言いたいことだが、このような試験のためのSpring MVCコー---
解決
それは何もしていないので、テストに合格した:)
あなたは@TestExecutionListeners
注釈を省略すると、、春は1と呼ばれるDependencyInjectionTestExecutionListener
含む3人のデフォルトのリスナーを登録します。これは@Resource
注釈を含む注入するもの、を探して、あなたのテストクラスをスキャンするリスナーです。このリスナーは理由未定義範囲を、tObj
を注入しようとし、そして失敗します。
@TestExecutionListeners({})
を宣言するときは、、あなたはDependencyInjectionTestExecutionListener
の登録を抑制し、そのテストがすべてで注入tObj
を取得したことがない、とあなたのテストがtObj
の存在をチェックされていないので、それは渡します。
それがこれを行うように、あなたのテストを変更し、それが失敗します:
@Test
public void testBean() {
assertNotNull("tObj is null", tObj);
}
のものはの起こらないので、あなたの空@TestExecutionListeners
とだから、テストは合格ます。
さて、あなたの元の問題への。あなたは、テストのコンテキストとリクエストスコープを登録しようとする場合は、WebApplicationContextUtils.registerWebApplicationScopes()
のソースコードを見て、あなたはラインを見つけることができます:
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
あなたはそれを試してみて、あなたが行く方法を見て、しかし、あなたが本当にテストでこれを行うためのものではないしているので、奇数副作用があるかもしれない可能性があります。
あなたがの必要性の要求が豆をスコープしないように、その代わり、私はあなたのテストを言い換えをお勧めします。これは、自己完結型のテストを書く場合@Test
のライフサイクルは、もはやリクエスト・スコープのBeanのライフサイクルよりもすべきではない、難しいことではありません。それは春の一環だとあなたはそれが動作を前提とすることができ、スコーピング・メカニズムをテストする必要はありません、覚えておいてください。
他のヒント
液春3.2以降
春からバージョン3.2 支援セクションの要求scoped豆の統合テスト.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
@WebAppConfiguration
public class SampleTest {
@Autowired WebApplicationContext wac;
@Autowired MockHttpServletRequest request;
@Autowired MockHttpSession session;
@Autowired MySessionBean mySessionBean;
@Autowired MyRequestBean myRequestBean;
@Test
public void requestScope() throws Exception {
assertThat(myRequestBean)
.isSameAs(request.getAttribute("myRequestBean"));
assertThat(myRequestBean)
.isSameAs(wac.getBean("myRequestBean", MyRequestBean.class));
}
@Test
public void sessionScope() throws Exception {
assertThat(mySessionBean)
.isSameAs(session.getAttribute("mySessionBean"));
assertThat(mySessionBean)
.isSameAs(wac.getBean("mySessionBean", MySessionBean.class));
}
}
詳細: エセッションScoped豆
液春前3.2とリスナー
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
@TestExecutionListeners({WebContextTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class})
public class SampleTest {
...
}
WebContextTestExecutionListener.java
public class WebContextTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void prepareTestInstance(TestContext testContext) {
if (testContext.getApplicationContext() instanceof GenericApplicationContext) {
GenericApplicationContext context = (GenericApplicationContext) testContext.getApplicationContext();
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST,
new SimpleThreadScope());
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION,
new SimpleThreadScope());
}
}
}
液春前3.2カスタムスコープ
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class, locations = "test-config.xml")
public class SampleTest {
...
}
TestConfig.java
@Configuration
@ComponentScan(...)
public class TestConfig {
@Bean
public CustomScopeConfigurer customScopeConfigurer(){
CustomScopeConfigurer scopeConfigurer = new CustomScopeConfigurer();
HashMap<String, Object> scopes = new HashMap<String, Object>();
scopes.put(WebApplicationContext.SCOPE_REQUEST,
new SimpleThreadScope());
scopes.put(WebApplicationContext.SCOPE_SESSION,
new SimpleThreadScope());
scopeConfigurer.setScopes(scopes);
return scopeConfigurer
}
またはxmlの設定
test-config.xml
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="request">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
<map>
<entry key="session">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
ソースコード
ソースコードのすべての発ソリューション
、私は「WebContextTestExecutionListener」とマリウスのソリューション@を含め、いくつかのソリューションを試みたが、それは私のために動作しませんでした。
最後に私を助けた答えは、新しいものではありませんが、それは良いことです: http://tarunsapra.wordpress.com/2011/06 / 28 / JUnitのスプリング・セッションおよび要求スコープ豆/ の
私は単に私の(テスト)アプリケーションコンテキストに次のコードを追加します:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="request">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
グッドラック!
あなたがリクエストスコープの豆を必要とするが、MockMVC
経由で任意の要求を行っていないときのために春4、でテストソリューション、など。
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(/* ... */)
public class Tests {
@Autowired
private GenericApplicationContext context;
@Before
public void defineRequestScope() {
context.getBeanFactory().registerScope(
WebApplicationContext.SCOPE_REQUEST, new RequestScope());
RequestContextHolder.setRequestAttributes(
new ServletRequestAttributes(new MockHttpServletRequest()));
}
// ...
これはまだ未解決の問題です。
https://jira.springsource.org/browse/SPR-4588する
で概説したように、私は、これはカスタムコンテキストローダーを定義することにより、(主に)仕事を得ることができました
テストリクエストスコープの豆うまくどのように登録して、春とカスタムスコープを作成します。
イド・コーンが説明したように、一言で言えば、それはテキストのコンテキストコンフィギュレーションに以下を追加するだけで十分です。
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="request">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
代わりにThreadLocalに基づいて事前に定義されたSimpleThreadScopeを、使用しての記事で説明したように、、それは、カスタム1を実装することも簡単です。
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
public class CustomScope implements Scope {
private final Map<String , Object> beanMap = new HashMap<String , Object>();
public Object get(String name, ObjectFactory<?> factory) {
Object bean = beanMap.get(name);
if (null == bean) {
bean = factory.getObject();
beanMap.put(name, bean);
}
return bean;
}
public String getConversationId() {
// not needed
return null;
}
public void registerDestructionCallback(String arg0, Runnable arg1) {
// not needed
}
public Object remove(String obj) {
return beanMap.remove(obj);
}
public Object resolveContextualObject(String arg0) {
// not needed
return null;
}
}
MariuszSのソリューションは、動作します。
新しくリリースされた3.2最後に行われた検査要求/セッションが豆に第一級オブジェクトをスコープのようです。ここでは詳細はブログのカップルがいます。
ロッセンStoyanchevの<のhref = "http://blog.springsource.org/2012/11/12/spring-framework-3-2-rc1-spring-mvc-test-framework/" のrel = "nofollowを" >春のフレームワーク3.2 RC1:Spring MVCのテストフレームワークの
サムBrannenの春フレームワーク3.2 RC1:新テストはの機能
時々ドキュメントを読んでいない1狂気を駆動します。ほぼます。
あなたは短い寿命の豆(例えばリクエストスコープ)を使用している場合は、最も可能性も、あなたの怠惰な初期化既定値を変更する必要があります!コンテキストがまだロードされているため、それ以外の場合はWebAppContextは、ロードし、あなたに欠けているのは勿論である行方不明要求スコープ、について何かを伝えるために失敗します!
<のhref = "http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-factory-lazy-init" のrel = "nofollowを「> http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-factory-lazy-init の
春の連中は間違いなく彼らの例外メッセージにそのヒントを置く必要があります...
デフォルトを変更したくない場合は、注釈の方法もあります:シングルトンは怠惰な初期化を行い、早すぎるリクエストスコープの豆をインスタンス化を避けるためになど@Component後に「@Lazy(真)」を置きます<。 / P>