我对单元测试还很陌生,所以请放轻松!我正在尝试使用一个相当简单的 Umbraco 8 项目作为测试平台。我目前一直在尝试测试注册依赖项的作曲家,并且很难弄清楚如何测试它。
代码可能会说话,所以不用多说,这是我想测试的作曲家。如您所见,它只是注册了一个针对接口编码的服务:
using Papermoon.Umbraco.Utils.Services;
using Papermoon.Umbraco.Utils.Services.Interfaces;
using Umbraco.Core;
using Umbraco.Core.Composing;
namespace Papermoon.Umbraco.Aldus.Core.Composers
{
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public class ServicesComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Register<IPapermoonContentTypeContainerService, PapermoonContentTypeContainerService>();
}
}
}
在玩了很多之后,我在 Umbraco 源代码中找到了一些代码,这意味着我可以根据注册类型的想法获得测试通过。但是,这绝不是在ServicesComposer
课程的背景下。因此,这不会影响我的代码覆盖率和实际测试类,而不是注册某些东西的能力。无论如何,这是代码:
using System;
using Moq;
using NUnit.Framework;
using Papermoon.Umbraco.Aldus.Core.Composers;
using Papermoon.Umbraco.Utils.Services;
using Papermoon.Umbraco.Utils.Services.Interfaces;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing.CompositionExtensions;
using Umbraco.Core.Logging;
namespace Papermoon.Umbraco.Aldus.Core.Tests.Composers
{
[TestFixture]
public class ServicesComposerTests
{
private ServicesComposer _servicesComposer;
[SetUp]
public void SetUp()
{
_servicesComposer = new ServicesComposer();
}
[Test]
public void Compose_WhenCalled_RegistersContentTypeContainerService()
{
Func<IFactory, IFactory> factoryFactory = null;
var mockedRegister = Mock.Of<IRegister>();
var mockedFactory = Mock.Of<IFactory>();
// the mocked register creates the mocked factory
Mock.Get(mockedRegister)
.Setup(x => x.CreateFactory())
.Returns(mockedFactory);
// the mocked register can register a factory factory
Mock.Get(mockedRegister)
.Setup(x => x.Register(It.IsAny<Func<IFactory, IFactory>>(), Lifetime.Singleton))
.Callback<Func<IFactory, IFactory>, Lifetime>((ff, lt) => factoryFactory = ff);
// the mocked factory can invoke the factory factory
Mock.Get(mockedFactory)
.Setup(x => x.GetInstance(typeof(IPapermoonContentTypeContainerService)))
.Returns(() => new Mock<IPapermoonContentTypeContainerService>().Object);
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
var typeLoader = new TypeLoader(Mock.Of<IAppPolicyCache>(), "", logger);
var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of<IRuntimeState>());
var factory = composition.CreateFactory();
var resolved = factory.GetInstance<IPapermoonContentTypeContainerService>();
Assert.IsNotNull(resolved);
}
}
}
下面的代码显示了我目前的位置,并且可能接近测试的样子(如果目前有点混乱)。我可能在这里偏离了目标,所以任何帮助都会风靡一时!
using System;
using Moq;
using NUnit.Framework;
using Papermoon.Umbraco.Aldus.Core.Composers;
using Papermoon.Umbraco.Utils.Services;
using Papermoon.Umbraco.Utils.Services.Interfaces;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing.CompositionExtensions;
using Umbraco.Core.Logging;
namespace Papermoon.Umbraco.Aldus.Core.Tests.Composers
{
[TestFixture]
public class ServicesComposerTests
{
private ServicesComposer _servicesComposer;
[SetUp]
public void SetUp()
{
_servicesComposer = new ServicesComposer();
Current.Factory = new Mock<IFactory>().Object;
}
[Test]
public void Compose_WhenCalled_RegistersContentTypeContainerService()
{
var mockedRegister = Mock.Of<IRegister>();
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
var typeLoader = new TypeLoader(Mock.Of<IAppPolicyCache>(), "", logger);
var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of<IRuntimeState>());
_servicesComposer.Compose(composition);
var resolved = Current.Factory.GetInstance<IPapermoonContentTypeContainerService>();
Assert.IsNotNull(resolved);
}
}
}
我还尝试模拟合成,看看我是否可以验证该Register
方法已运行,但由于这是一个静态方法,我收到以下错误:
Extension methods (here: RegisterExtensions.Register) may not be used in setup / verification expressions.
这是让我遇到该错误的代码:
[Test]
public void Compose_WhenCalled_RegistersContentTypeContainerService()
{
Func<IFactory, IFactory> factoryFactory = null;
var mockedRegister = Mock.Of<IRegister>();
var mockedFactory = Mock.Of<IFactory>();
// the mocked register creates the mocked factory
Mock.Get(mockedRegister)
.Setup(x => x.CreateFactory())
.Returns(mockedFactory);
Mock.Get(mockedRegister)
.Setup(x => x.Register(It.IsAny<Func<IFactory, IFactory>>(), Lifetime.Singleton))
.Callback<Func<IFactory, IFactory>, Lifetime>((ff, lt) => factoryFactory = ff);
// the mocked factory can invoke the factory factory
Mock.Get(mockedFactory)
.Setup(x => x.GetInstance(typeof(IFactory)))
.Returns(() => factoryFactory?.Invoke(mockedFactory));
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
var typeLoader = new TypeLoader(Mock.Of<IAppPolicyCache>(), "", logger);
var composition = new Mock<Composition>(mockedRegister, typeLoader, logger, new Mock<IRuntimeState>().Object);
composition.Verify(c => c.Register<IPapermoonContentTypeContainerService, PapermoonContentTypeContainerService>(It.IsAny<Lifetime>()));
}
最终,我失败了(可能我的目标太高了!),我不能 100% 确定要在这里测试什么。我的想法是我想测试运行IPapermoonContentTypeContainerService
后是否可解析,_serviceComposer.Compose
即它不是 null 以确保它已注册到容器中。在这一点上这可能是不可能的,我想知道composition.Register<IPapermoonContentTypeContainerService, PapermoonContentTypeContainerService>();
被调用的测试是否足够(因为实际的注册部分是第三方的,因此不被测试)。或者,我是不是找错了树,实际上根本不应该对其进行测试?
谢谢!
本