2016-03-06 254 views
1

我正在嘗試使用Guice嘗試使用Play framework 2.4.6進行控制器測試時遇到錯誤。它發生在Controller中的任何view.render代碼中。 redirect不會產生此問題。控制器測試 - CacheManager已關閉。它不能再使用

堆棧:

1) Error in custom provider, java.lang.IllegalStateException: The CacheManager has been shut down. It can no longer be used. 
    at play.api.cache.EhCacheModule.play$api$cache$EhCacheModule$$bindCache$1(Cache.scala:178): 
Binding(interface net.sf.ehcache.Ehcache qualified with QualifierInstance(@play.cache.NamedCache(value=play)) to ProviderTarget([email protected])) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1) 
    while locating net.sf.ehcache.Ehcache annotated with @play.cache.NamedCache(value=play) 
    at play.api.cache.EhCacheModule.play$api$cache$EhCacheModule$$bindCache$1(Cache.scala:179): 
Binding(interface play.api.cache.CacheApi qualified with QualifierInstance(@play.cache.NamedCache(value=play)) to ProviderTarget([email protected])) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1) 
    while locating play.api.cache.CacheApi annotated with @play.cache.NamedCache(value=play) 
    while locating play.api.cache.CacheApi 
    for parameter 0 at play.cache.DefaultCacheApi.<init>(DefaultCacheApi.java:20) 
    at play.cache.DefaultCacheApi.class(DefaultCacheApi.java:20) 
    while locating play.cache.DefaultCacheApi 
    while locating play.cache.CacheApi 

下面是我的設置:

控制器:

@Singleton 
public class AccountController extends Controller { 
    private AccountService accountService; 

    @Inject 
    public Controller(AccountService a) { 
     accountService = a; 
    } 

    public Result addAccount() { 
    boolean success = accountService.addAccount(); 
    if (success) 
     return ok(CreateAccount.render());//<--THIS TRIGGERS THE ERROR WHEN RUNNING THE TEST 
    } 
} 

接口:

@ImplementedBy(AccountServiceImpl.class) 
public interface AccountService { 
    boolean addAccount(); 
} 

實現:

public class AccountServiceImpl implements AccountService { 
    @Override 
    public boolean addAccount() { 
    } 
} 

測試:

public class TestClass { 
@Inject 
Application application; 

final AccountService accountServiceMock = mock(AccountService.class); 

@Before 
public void setup() { 
    Module testModule = new AbstractModule() { 
     @Override 
     public void configure() { 
      bind(AccountService.class).toInstance(accountServiceMock); 
     } 
    }; 

    GuiceApplicationBuilder builder = new GuiceApplicationLoader() 
      .builder(new ApplicationLoader.Context(Environment.simple())) 
      .overrides(testModule); 
    Guice.createInjector(builder.applicationModule()).injectMembers(this); 

    Helpers.start(application); 
} 

@Test 
public void testMethod() throws Exception { 
    RequestBuilder request = new RequestBuilder() 
      .session("userId", "1") 
      .uri(controllers.routes.AccountController.addAccount().url()); 

    running(application,() -> { 
     when(accountServiceMock.addAccount().thenReturn(true); 
     assertEquals(OK, route(request).status()); 
    }); 

} 

任何他LP讚賞!

編輯:我確定了導致問​​題的確切的東西,但我仍然不知道爲什麼。

RequestBuilder request = new RequestBuilder() 
      .session("userId", "1") // <--- THIS IS CAUSING THE PROBLEM 
      .uri(controllers.routes.AccountController.addAccount().url()); 

爲了更加準確:

"userId" // <--- THIS. userIds, or any other I've tried, solved the issue. 

爲了能夠長時間再次恢復,因爲userId會話時,測試方法與控制器view.render沿設置RequestBuilder,這個錯誤發生。

這是不管我是否在我的html或甚至在控制器中使用這樣的會話。任何人都知道這裏發生了什麼?

+0

你在哪裏實例化你的應用程序?你不應該在(classLoader).in(Mode.TEST).build();'中使用'application = new GuiceApplicationBuilder()。 – Kris

+0

@Kris我相信所有需要的設置都已經在使用'@ Before''註釋的setup方法中。 再次實例化''application''會導致''沒有執行play.Application被綁定.'''''''' – DxHito

+0

也許你是對的。無論如何,我在我的測試用例'ClassLoader classLoader = FakeApplication.class中啓動一個FakeApplication。getClassLoader();應用程序= new GuiceApplicationBuilder()。in(classLoader).in(Mode.TEST).build(); Helpers.start(應用程序);'。但是在我看來,在Play中編寫測試時,更多的嘗試和錯誤。如果有效,我堅持下去。 :) – Kris

回答

0

移動測試方法裏面一切的running調用內部:

running(application,() -> { 
    RequestBuilder request = new RequestBuilder() 
     .session("userId", "1") 
     .uri(controllers.routes.AccountController.addAccount().url()); 

    when(accountServiceMock.addAccount().thenReturn(true); 
    assertEquals(OK, route(request).status()); 
}); 

running method停止應用程序,然後你在你的assert路由的請求時,得到一個錯誤。

+0

我很抱歉!我不小心複製了粘貼的舊版本的代碼。我編輯了這個問題 - assertEquals實際上是在「running」中。如果不是,則會導致java.lang.RuntimeException:沒有啓動應用程序。我現在試着把''RequestBuilder''放進去,仍然導致CacheManager錯誤。 – DxHito