using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Linq; using System.Linq.Expressions; using System.Web; using Moq; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Services; using Umbraco.Tests.Testing.Objects.Accessors; using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; namespace Umbraco.Tests.TestHelpers { /// /// Provides objects for tests. /// internal partial class TestObjects { /// /// Gets a mocked IUmbracoDatabaseFactory. /// /// An IUmbracoDatabaseFactory. /// A value indicating whether the factory is configured. /// A value indicating whether the factory can connect to the database. /// This is just a void factory that has no actual database. public IUmbracoDatabaseFactory GetDatabaseFactoryMock(bool configured = true, bool canConnect = true) { var sqlSyntax = new SqlCeSyntaxProvider(); var sqlContext = Mock.Of(); Mock.Get(sqlContext).Setup(x => x.SqlSyntax).Returns(sqlSyntax); var databaseFactoryMock = new Mock(); databaseFactoryMock.Setup(x => x.Configured).Returns(configured); databaseFactoryMock.Setup(x => x.CanConnect).Returns(canConnect); databaseFactoryMock.Setup(x => x.SqlContext).Returns(sqlContext); // can create a database - but don't try to use it! if (configured && canConnect) databaseFactoryMock.Setup(x => x.CreateDatabase()).Returns(GetUmbracoSqlCeDatabase(Mock.Of())); return databaseFactoryMock.Object; } /// /// Gets a mocked service context built with mocked services. /// /// A ServiceContext. public ServiceContext GetServiceContextMock(IFactory container = null) { // FIXME: else some tests break - figure it out container = null; return ServiceContext.CreatePartial( MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container), MockService(container)); } private T MockService(IFactory container = null) where T : class { return container?.TryGetInstance() ?? new Mock().Object; } /// /// Gets an opened database connection that can begin a transaction. /// /// A DbConnection. /// This is because NPoco wants a DbConnection, NOT an IDbConnection, /// and DbConnection is hard to mock so we create our own class here. public DbConnection GetDbConnection() { return new MockDbConnection(); } /// /// Gets an Umbraco context. /// /// An Umbraco context. /// This should be the minimum Umbraco context. public UmbracoContext GetUmbracoContextMock(IUmbracoContextAccessor accessor = null) { var httpContext = Mock.Of(); var publishedSnapshotMock = new Mock(); publishedSnapshotMock.Setup(x => x.Members).Returns(Mock.Of()); var publishedSnapshot = publishedSnapshotMock.Object; var publishedSnapshotServiceMock = new Mock(); publishedSnapshotServiceMock.Setup(x => x.CreatePublishedSnapshot(It.IsAny())).Returns(publishedSnapshot); var publishedSnapshotService = publishedSnapshotServiceMock.Object; var umbracoSettings = GetUmbracoSettings(); var globalSettings = GetGlobalSettings(); var urlProviders = new UrlProviderCollection(Enumerable.Empty()); var mediaUrlProviders = new MediaUrlProviderCollection(Enumerable.Empty()); if (accessor == null) accessor = new TestUmbracoContextAccessor(); var umbracoContextFactory = new UmbracoContextFactory( accessor, publishedSnapshotService, new TestVariationContextAccessor(), new TestDefaultCultureAccessor(), umbracoSettings, globalSettings, urlProviders, mediaUrlProviders, Mock.Of()); return umbracoContextFactory.EnsureUmbracoContext(httpContext).UmbracoContext; } public IUmbracoSettingsSection GetUmbracoSettings() { // FIXME: Why not use the SettingsForTest.GenerateMock ... ? // FIXME: Shouldn't we use the default ones so they are the same instance for each test? var umbracoSettingsMock = new Mock(); var webRoutingSectionMock = new Mock(); webRoutingSectionMock.Setup(x => x.UrlProviderMode).Returns(UrlMode.Auto.ToString()); umbracoSettingsMock.Setup(x => x.WebRouting).Returns(webRoutingSectionMock.Object); return umbracoSettingsMock.Object; } public IGlobalSettings GetGlobalSettings() { return SettingsForTests.GetDefaultGlobalSettings(); } public IFileSystems GetFileSystemsMock() { var fileSystems = Mock.Of(); MockFs(fileSystems, x => x.MacroPartialsFileSystem); MockFs(fileSystems, x => x.MvcViewsFileSystem); MockFs(fileSystems, x => x.PartialViewsFileSystem); MockFs(fileSystems, x => x.ScriptsFileSystem); MockFs(fileSystems, x => x.StylesheetsFileSystem); return fileSystems; } private void MockFs(IFileSystems fileSystems, Expression> fileSystem) { var fs = Mock.Of(); Mock.Get(fileSystems).Setup(fileSystem).Returns(fs); } #region Inner classes private class MockDbConnection : DbConnection { protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) { return Mock.Of(); // enough here } public override void Close() { throw new NotImplementedException(); } public override void ChangeDatabase(string databaseName) { throw new NotImplementedException(); } public override void Open() { throw new NotImplementedException(); } public override string ConnectionString { get; set; } protected override DbCommand CreateDbCommand() { throw new NotImplementedException(); } public override string Database { get; } public override string DataSource { get; } public override string ServerVersion { get; } public override ConnectionState State => ConnectionState.Open; // else NPoco reopens } public class TestDataTypeService : IDataTypeService { public TestDataTypeService() { DataTypes = new Dictionary(); } public TestDataTypeService(params IDataType[] dataTypes) { DataTypes = dataTypes.ToDictionary(x => x.Id, x => x); } public TestDataTypeService(IEnumerable dataTypes) { DataTypes = dataTypes.ToDictionary(x => x.Id, x => x); } public Dictionary DataTypes { get; } public Attempt> CreateContainer(int parentId, string name, int userId = -1) { throw new NotImplementedException(); } public Attempt SaveContainer(EntityContainer container, int userId = -1) { throw new NotImplementedException(); } public EntityContainer GetContainer(int containerId) { throw new NotImplementedException(); } public EntityContainer GetContainer(Guid containerId) { throw new NotImplementedException(); } public IEnumerable GetContainers(string folderName, int level) { throw new NotImplementedException(); } public IEnumerable GetContainers(IDataType dataType) { throw new NotImplementedException(); } public IEnumerable GetContainers(int[] containerIds) { throw new NotImplementedException(); } public Attempt DeleteContainer(int containerId, int userId = -1) { throw new NotImplementedException(); } public Attempt> RenameContainer(int id, string name, int userId = -1) { throw new NotImplementedException(); } public IDataType GetDataType(string name) { throw new NotImplementedException(); } public IDataType GetDataType(int id) { DataTypes.TryGetValue(id, out var dataType); return dataType; } public IDataType GetDataType(Guid id) { throw new NotImplementedException(); } public IEnumerable GetAll(params int[] ids) { if (ids.Length == 0) return DataTypes.Values; return ids.Select(x => DataTypes.TryGetValue(x, out var dataType) ? dataType : null).WhereNotNull(); } public void Save(IDataType dataType, int userId = -1) { throw new NotImplementedException(); } public void Save(IEnumerable dataTypeDefinitions, int userId = -1) { throw new NotImplementedException(); } public void Save(IEnumerable dataTypeDefinitions, int userId, bool raiseEvents) { throw new NotImplementedException(); } public void Delete(IDataType dataType, int userId = -1) { throw new NotImplementedException(); } public IEnumerable GetByEditorAlias(string propertyEditorAlias) { throw new NotImplementedException(); } public Attempt> Move(IDataType toMove, int parentId) { throw new NotImplementedException(); } public IReadOnlyDictionary> GetReferences(int id) { throw new NotImplementedException(); } } #endregion } }