我面臨的問題是,使用同一個鍵從彈簧緩存方法返回的兩個對象失敗assertSame測試。爲什麼這些對象不共享一個相同的存儲區域?Spring Casheable返回的緩存對象失敗等同性檢查
詳細信息: 我使用redis緩存機制在spring boot REST api中實現緩存。 緩存以它首先從外部提供的源(JPS存儲庫訪問數據庫)中檢索數據的方式正確工作,然後對相同緩存鍵的後續調用將從緩存中返回數據。但是,我無法在JUnit測試用例中完全模仿這種行爲。我的assertEquals或assertSame在緩存返回的2個對象上失敗。
我的代碼庫看起來如下: MVN依賴關係:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.6.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
Spring應用程序配置:
@SpringBootApplication
@EnableCaching
public class Application {
@Value("${redis.host}")
private String redisHost;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConFactory = new JedisConnectionFactory();
jedisConFactory.setHostName(redisHost);
jedisConFactory.setPort(6379);
return jedisConFactory;
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(jedisConnectionFactory());
return template;
}
@Bean
CacheManager cacheManager() {
return new RedisCacheManager(redisTemplate());
}
服務類:
@Service
public class CIDomainService {
private RedisTemplate<String, Object> redisTemplate;
private CIDomainDAO ciDomainDAO;
@Autowired
public CIDomainService(CIDomainDAO ciDomainDAO, RedisTemplate<String, Object> redisTemplate) {
this.ciDomainDAO = ciDomainDAO;
this.redisTemplate = redisTemplate;
}
@Cacheable(value = "ciDomain", key = "#id")
public CIDomain getCIDomain(int id) {
CIDomain ciDomain = new CIDomain();
ciDomain.setId(id);
ciDomain.setName("SomeName");
return ciDomain;
}
public void clearAllCache() {
redisTemplate.delete("listCIDomains");
redisTemplate.delete("ciDomain");
}
}
上述服務中的ciDomainDAO只是使用findAll()方法從外部數據庫或內存數據庫檢索數據的JPS存儲庫接口。我的測試類:
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("local")
@SpringBootTest
public class CIDomainServiceIntegrationTest {
@Autowired
CIDomainService ciDomainServiceSpy;
@Before
public void setUp(){
ciDomainServiceSpy.clearAllCache();
}
@Test
public void listCIDomains_ShouldRetrieveCIDomainsWithCachingPluggedIn() {
CIDomain domain1 = ciDomainServiceSpy.getCIDomain(1);
CIDomain domain2 = ciDomainServiceSpy.getCIDomain(2);
CIDomain domain3 = ciDomainServiceSpy.getCIDomain(1);
assertSame(domain1, domain3); //fails
}
我的域類:
@Entity
@Table(name = "CI_DOMAIN")
public class CIDomain implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
基於this post據我所知,對象是從庫中檢索的第一個電話,再後來的通話將獲取提供從緩存中該對象提供了相同的「密鑰」。我在上面的測試用例中做了同樣的事情,但assertSame失敗。 Spring緩存必須將緩存對象存儲在爲給定請求獲取的內存中。爲什麼每次發送同一個請求的密鑰都會發送不同的對象。
我試圖有一個替代解決方案,我在服務類中使用間諜並驗證基於相同密鑰請求的方法調用。但是,我遇到了不同的問題。在服務類上創建間諜甚至不使用緩存機制,即使提供了相同的密鑰,也會調用服務getCIDomain方法。我跟着this,this,this,this,this和很多其他的帖子進行進一步的分析,但無法通過assertSame的間諜得到它的工作。
任何幫助真的不勝感激。
,如果他們都相同,則正在檢查('assertSame'(,他們不應該。等於('assertEqual')。相等和相同是不同的事情。對於後者的傳遞,你需要在你的域對象中使用'equals'和'hashCode'方法。 –
@ M.Deinum感謝你的迴應。根據序列化和反序列化「相同」(等於傳遞)java對象h的事實推理您的評論作爲兩個不同的引用或ID,因此object1 == object2將爲false。然而,使用equals而不是assertSame對我來說是有問題的,因爲我認爲「我需要使用assertSame,否則代碼依賴於.equals(Object),它沒有被顯示,可能已被覆蓋比較所有屬性,然後這個測試總是會通過,即使沒有任何東西被緩存。「 – Vishal
同樣不等於。 assertSame不會'domain1 == domain3'這不會是這種情況,因爲它是一個不同的對象實例。你應該真的使用'equals.'而不是別的。如前所述,由您自己來說,緩存(由於使用Redis)會對對象進行序列化和序列化,因此它們將永遠不會相同。即使你使用java序列化,對象也永遠不會相同。相信我,你必須檢查對象的平等,而不是如果他們是相同的(他們永遠不會)。 –