Files
Umbraco-CMS/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs

193 lines
7.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Routing;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
using Umbraco.Core.Strings;
using Umbraco.Core.Sync;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Testing;
using Umbraco.Tests.Testing.Objects.Accessors;
using Umbraco.Web;
using Umbraco.Web.Cache;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.PublishedCache.NuCache;
using Umbraco.Web.PublishedCache.NuCache.DataSource;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
namespace Umbraco.Tests.Scoping
{
[TestFixture]
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true)]
public class ScopedNuCacheTests : TestWithDatabaseBase
{
private DistributedCacheBinder _distributedCacheBinder;
protected override void Compose()
{
base.Compose();
// the cache refresher component needs to trigger to refresh caches
// but then, it requires a lot of plumbing ;(
// FIXME: and we cannot inject a DistributedCache yet
// so doing all this mess
Composition.RegisterUnique<IServerMessenger, ScopedXmlTests.LocalServerMessenger>();
Composition.RegisterUnique(f => Mock.Of<IServerRegistrar>());
Composition.WithCollectionBuilder<CacheRefresherCollectionBuilder>()
.Add(() => Composition.TypeLoader.GetCacheRefreshers());
}
public override void TearDown()
{
base.TearDown();
_distributedCacheBinder?.UnbindEvents();
_distributedCacheBinder = null;
_onPublishedAssertAction = null;
ContentService.Published -= OnPublishedAssert;
}
private void OnPublishedAssert(IContentService sender, PublishEventArgs<IContent> args)
{
_onPublishedAssertAction?.Invoke();
}
private Action _onPublishedAssertAction;
protected override IPublishedSnapshotService CreatePublishedSnapshotService()
{
var options = new PublishedSnapshotServiceOptions { IgnoreLocalDb = true };
var publishedSnapshotAccessor = new UmbracoContextPublishedSnapshotAccessor(Umbraco.Web.Composing.Current.UmbracoContextAccessor);
var runtimeStateMock = new Mock<IRuntimeState>();
runtimeStateMock.Setup(x => x.Level).Returns(() => RuntimeLevel.Run);
var contentTypeFactory = Factory.GetInstance<IPublishedContentTypeFactory>();
var documentRepository = Mock.Of<IDocumentRepository>();
var mediaRepository = Mock.Of<IMediaRepository>();
var memberRepository = Mock.Of<IMemberRepository>();
return new PublishedSnapshotService(
options,
null,
runtimeStateMock.Object,
ServiceContext,
contentTypeFactory,
null,
publishedSnapshotAccessor,
Mock.Of<IVariationContextAccessor>(),
ProfilingLogger,
ScopeProvider,
documentRepository, mediaRepository, memberRepository,
DefaultCultureAccessor,
new DatabaseDataSource(),
Factory.GetInstance<IGlobalSettings>(),
Factory.GetInstance<IEntityXmlSerializer>(),
Mock.Of<IPublishedModelFactory>(),
new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider() }),
new TestSyncBootStateAccessor(SyncBootState.WarmBoot));
}
protected UmbracoContext GetUmbracoContextNu(string url, int templateId = 1234, RouteData routeData = null, bool setSingleton = false, IUmbracoSettingsSection umbracoSettings = null, IEnumerable<IUrlProvider> urlProviders = null)
{
// ensure we have a PublishedSnapshotService
var service = PublishedSnapshotService as PublishedSnapshotService;
var httpContext = GetHttpContextFactory(url, routeData).HttpContext;
var globalSettings = TestObjects.GetGlobalSettings();
var umbracoContext = new UmbracoContext(
httpContext,
service,
new WebSecurity(httpContext, Current.Services.UserService, globalSettings),
umbracoSettings ?? SettingsForTests.GetDefaultUmbracoSettings(),
urlProviders ?? Enumerable.Empty<IUrlProvider>(),
Enumerable.Empty<IMediaUrlProvider>(),
globalSettings,
new TestVariationContextAccessor());
if (setSingleton)
Umbraco.Web.Composing.Current.UmbracoContextAccessor.UmbracoContext = umbracoContext;
return umbracoContext;
}
[TestCase(true)]
[TestCase(false)]
public void TestScope(bool complete)
{
var umbracoContext = GetUmbracoContextNu("http://example.com/", setSingleton: true);
// wire cache refresher
_distributedCacheBinder = new DistributedCacheBinder(new DistributedCache(), Mock.Of<IUmbracoContextFactory>(), Mock.Of<ILogger>());
_distributedCacheBinder.BindEvents(true);
// create document type, document
var contentType = new ContentType(-1) { Alias = "CustomDocument", Name = "Custom Document" };
Current.Services.ContentTypeService.Save(contentType);
var item = new Content("name", -1, contentType);
// event handler
var evented = 0;
_onPublishedAssertAction = () =>
{
evented++;
var e = umbracoContext.Content.GetById(item.Id);
// during events, due to LiveSnapshot, we see the changes
Assert.IsNotNull(e);
Assert.AreEqual("changed", e.Name());
};
using (var scope = ScopeProvider.CreateScope())
{
Current.Services.ContentService.SaveAndPublish(item);
scope.Complete();
}
// been created
var x = umbracoContext.Content.GetById(item.Id);
Assert.IsNotNull(x);
Assert.AreEqual("name", x.Name());
ContentService.Published += OnPublishedAssert;
using (var scope = ScopeProvider.CreateScope())
{
item.Name = "changed";
Current.Services.ContentService.SaveAndPublish(item);
if (complete)
scope.Complete();
}
// only 1 event occuring because we are publishing twice for the same event for
// the same object and the scope deduplicates the events (uses the latest)
Assert.AreEqual(complete ? 1 : 0, evented);
// after the scope,
// if completed, we see the changes
// else changes have been rolled back
x = umbracoContext.Content.GetById(item.Id);
Assert.IsNotNull(x);
Assert.AreEqual(complete ? "changed" : "name", x.Name());
}
}
}