2016-11-26 62 views
1

Spring似乎在我的測試環境中隨機加載了bean。在Spock集成測試中嘲笑JPA存儲庫

我有如下庫類User

@Repository 
public interface UserRepository extends JpaRepository<User, Long> { 

    User findOneByExternalId(Long externalId); 

    Optional<User> findOneById(Long id); 

} 

,它的測試相當於:

@Primary 
@Repository(value = "userRepository") 
public interface TestUserRepository extends UserRepository { 

    Long TEST_CORRECT_USER_ID = 1L; 
    Long TEST_INCORRECT_USER_ID = 2L; 

    @Override 
    default User findOneByExternalId(Long externalId) { 
     return getTestUser(externalId); 
    } 

    @Override 
    default Optional<User> findOneById(Long id) { 
     return ofNullable(getTestUser(id)); 
    } 

    default User getTestUser(Long id) { 
     if (TEST_CORRECT_USER_ID.equals(id)) { 
      User user = new User(); 
      user.setExternalId(id); 
      user.setDevices(emptyList()); 
      user.setId(id); 
      return user; 
     } 
     else { 
      return null; 
     } 
    } 

} 

,另外兩個爲Device

@Repository 
public interface DeviceRepository extends JpaRepository<Device, Long> { 

    Optional<Device> findOneByDeviceId(String deviceId); 

    Optional<Device> findOneByDeviceIdAndToken(String deviceId, String token); 

} 

測試相當於:

@Primary 
@Repository(value = "deviceRepository") 
public interface TestDeviceRepository extends DeviceRepository { 

    @Override 
    default <S extends Device> S save(S device) { 
     return device; 
    } 

} 

測試下面通過對UserRepository,而不是爲DeviceRepository:它

@SpringBootTest(classes = Application) 
@ContextConfiguration(classes = [TestDeviceRepository, TestUserRepository]) 
class IntegrationContextSpecTest extends Specification { 

    @Autowired 
    ApplicationContext applicationContext 

    @Unroll("Bean #bean should be instance of #clazz") 
    def "should initialize test beans instead of normal beans"() { 
     expect: 
     clazz.isAssignableFrom(applicationContext.getBean(bean). 
             getClass()) 

     where: 
     bean    | clazz 
     UserRepository | TestUserRepository 
     DeviceRepository | TestDeviceRepository 
    } 

} 

可能是什麼原因?我重複了applicationContext的內容,它清楚地表明我的UserRepository bean的名稱爲userRepository,我的DeviceRepository的名稱爲deviceRepository

這裏的輸出從測試:

Condition not satisfied: 

clazz.isAssignableFrom(applicationContext.getBean(bean).getClass()) 
|  |    |     |  |  | 
|  false   |     |  |  class com.sun.proxy.$Proxy143 
|      |     |  interface com.example.repository.DeviceRepository 
|      |     org.[email protected]10e4cf09 
|      org.s[email protected]7dc51783: startup date [Sun Nov 27 22:09:16 CET 2016]; parent: org.spring[email protected]56aaaecd 
interface com.example.test.integration.mock.TestDeviceRepository 
+1

它是如何失敗?什麼信息? – Opal

+1

如何刪除'@ Primary'註釋? –

+0

@Opal它說'DeviceRepository' bean不是'TestDeviceRepository'的一個實例。我認爲這很明顯,對不起!錯誤中有關於DeviceRepository類是否是代理的信息(如預期的那樣,畢竟它是JPA魔術),所以沒有什麼特別的用處。 – Jezor

回答

3

最簡單的解決方案,有時最難以想到的。我承認我太過分地解決了這個問題。

我不得不這樣做的是使用@Profile註釋,如:

@Repository 
@Profile("!test") 
public interface DeviceRepository extends JpaRepository<Device, Long> { 
    /* ... implementation... */ 
} 

,並在測試類

@Repository 
@Profile("test") 
public interface TestDeviceRepository extends DeviceRepository { 
    /* ... implementation... */ 
} 

現在我所有的測試都通過!