11// Copyright (c) Umbraco.
22// See LICENSE for more details.
33
4- using System . Collections . Generic ;
5- using System . Linq ;
4+ using Microsoft . Extensions . Logging ;
5+ using Moq ;
66using NUnit . Framework ;
77using Umbraco . Cms . Core ;
8+ using Umbraco . Cms . Core . Cache ;
89using Umbraco . Cms . Core . Models ;
910using Umbraco . Cms . Core . Persistence . Repositories ;
1011using Umbraco . Cms . Core . Services ;
12+ using Umbraco . Cms . Infrastructure . Persistence . Repositories . Implement ;
13+ using Umbraco . Cms . Infrastructure . Scoping ;
1114using Umbraco . Cms . Tests . Common . Testing ;
1215using Umbraco . Cms . Tests . Integration . Testing ;
1316
@@ -22,6 +25,16 @@ internal sealed class DictionaryRepositoryTest : UmbracoIntegrationTest
2225
2326 private IDictionaryRepository CreateRepository ( ) => GetRequiredService < IDictionaryRepository > ( ) ;
2427
28+ private IDictionaryRepository CreateRepositoryWithCache ( AppCaches cache ) =>
29+
30+ // Create a repository with a real runtime cache.
31+ new DictionaryRepository (
32+ GetRequiredService < IScopeAccessor > ( ) ,
33+ cache ,
34+ GetRequiredService < ILogger < DictionaryRepository > > ( ) ,
35+ GetRequiredService < ILoggerFactory > ( ) ,
36+ GetRequiredService < ILanguageRepository > ( ) ) ;
37+
2538 [ Test ]
2639 public async Task Can_Perform_Get_By_Key_On_DictionaryRepository ( )
2740 {
@@ -396,6 +409,134 @@ public void Can_Perform_GetDictionaryItemKeyMap_On_DictionaryRepository()
396409 }
397410 }
398411
412+ [ Test ]
413+ public void Can_Perform_Cached_Request_For_Existing_Value_By_Key_On_DictionaryRepository_With_Cache ( )
414+ {
415+ var cache = AppCaches . Create ( Mock . Of < IRequestCache > ( ) ) ;
416+ var repository = CreateRepositoryWithCache ( cache ) ;
417+
418+ using ( ScopeProvider . CreateScope ( ) )
419+ {
420+ var dictionaryItem = repository . Get ( "Read More" ) ;
421+
422+ Assert . AreEqual ( "Read More" , dictionaryItem . Translations . Single ( x => x . LanguageIsoCode == "en-US" ) . Value ) ;
423+ }
424+
425+ // Modify the value directly in the database. This won't be reflected in the repository cache and hence if the cache
426+ // is working as expected we should get the same value as above.
427+ using ( var scope = ScopeProvider . CreateScope ( ) )
428+ {
429+ scope . Database . Execute ( "UPDATE cmsLanguageText SET value = 'Read More (updated)' WHERE value = 'Read More' and LanguageId = 1" ) ;
430+ scope . Complete ( ) ;
431+ }
432+
433+ using ( ScopeProvider . CreateScope ( ) )
434+ {
435+ var dictionaryItem = repository . Get ( "Read More" ) ;
436+
437+ Assert . AreEqual ( "Read More" , dictionaryItem . Translations . Single ( x => x . LanguageIsoCode == "en-US" ) . Value ) ;
438+ }
439+
440+ cache . IsolatedCaches . ClearCache < IDictionaryItem > ( ) ;
441+ using ( ScopeProvider . CreateScope ( ) )
442+ {
443+ var dictionaryItem = repository . Get ( "Read More" ) ;
444+
445+ Assert . AreEqual ( "Read More (updated)" , dictionaryItem . Translations . Single ( x => x . LanguageIsoCode == "en-US" ) . Value ) ;
446+ }
447+ }
448+
449+ [ Test ]
450+ public void Can_Perform_Cached_Request_For_NonExisting_Value_By_Key_On_DictionaryRepository_With_Cache ( )
451+ {
452+ var cache = AppCaches . Create ( Mock . Of < IRequestCache > ( ) ) ;
453+ var repository = CreateRepositoryWithCache ( cache ) ;
454+
455+ using ( ScopeProvider . CreateScope ( ) )
456+ {
457+ var dictionaryItem = repository . Get ( "Read More Updated" ) ;
458+
459+ Assert . IsNull ( dictionaryItem ) ;
460+ }
461+
462+ // Modify the value directly in the database such that it now exists. This won't be reflected in the repository cache and hence if the cache
463+ // is working as expected we should get the same null value as above.
464+ using ( var scope = ScopeProvider . CreateScope ( ) )
465+ {
466+ scope . Database . Execute ( "UPDATE cmsDictionary SET [key] = 'Read More Updated' WHERE [key] = 'Read More'" ) ;
467+ scope . Complete ( ) ;
468+ }
469+
470+ using ( ScopeProvider . CreateScope ( ) )
471+ {
472+ var dictionaryItem = repository . Get ( "Read More Updated" ) ;
473+
474+ Assert . IsNull ( dictionaryItem ) ;
475+ }
476+
477+ cache . IsolatedCaches . ClearCache < IDictionaryItem > ( ) ;
478+ using ( ScopeProvider . CreateScope ( ) )
479+ {
480+ var dictionaryItem = repository . Get ( "Read More Updated" ) ;
481+
482+ Assert . IsNotNull ( dictionaryItem ) ;
483+ }
484+ }
485+
486+ [ Test ]
487+ public void Cannot_Perform_Cached_Request_For_Existing_Value_By_Key_On_DictionaryRepository_Without_Cache ( )
488+ {
489+ var repository = CreateRepository ( ) ;
490+
491+ using ( ScopeProvider . CreateScope ( ) )
492+ {
493+ var dictionaryItem = repository . Get ( "Read More" ) ;
494+
495+ Assert . AreEqual ( "Read More" , dictionaryItem . Translations . Single ( x => x . LanguageIsoCode == "en-US" ) . Value ) ;
496+ }
497+
498+ // Modify the value directly in the database. As we don't have caching enabled on the repository we should get the new value.
499+ using ( var scope = ScopeProvider . CreateScope ( ) )
500+ {
501+ scope . Database . Execute ( "UPDATE cmsLanguageText SET value = 'Read More (updated)' WHERE value = 'Read More' and LanguageId = 1" ) ;
502+ scope . Complete ( ) ;
503+ }
504+
505+ using ( ScopeProvider . CreateScope ( ) )
506+ {
507+ var dictionaryItem = repository . Get ( "Read More" ) ;
508+
509+ Assert . AreEqual ( "Read More (updated)" , dictionaryItem . Translations . Single ( x => x . LanguageIsoCode == "en-US" ) . Value ) ;
510+ }
511+ }
512+
513+ [ Test ]
514+ public void Cannot_Perform_Cached_Request_For_NonExisting_Value_By_Key_On_DictionaryRepository_Without_Cache ( )
515+ {
516+ var repository = CreateRepository ( ) ;
517+
518+ using ( ScopeProvider . CreateScope ( ) )
519+ {
520+ var dictionaryItem = repository . Get ( "Read More Updated" ) ;
521+
522+ Assert . IsNull ( dictionaryItem ) ;
523+ }
524+
525+ // Modify the value directly in the database such that it now exists. As we don't have caching enabled on the repository we should get the new value.
526+ using ( var scope = ScopeProvider . CreateScope ( ) )
527+ {
528+ scope . Database . Execute ( "UPDATE cmsDictionary SET [key] = 'Read More Updated' WHERE [key] = 'Read More'" ) ;
529+ scope . Complete ( ) ;
530+ }
531+
532+ using ( ScopeProvider . CreateScope ( ) )
533+ {
534+ var dictionaryItem = repository . Get ( "Read More Updated" ) ;
535+
536+ Assert . IsNotNull ( dictionaryItem ) ;
537+ }
538+ }
539+
399540 public async Task CreateTestData ( )
400541 {
401542 var languageService = GetRequiredService < ILanguageService > ( ) ;
0 commit comments