public class IoCModule : Autofac.Module { protected override void Load(Autofac.ContainerBuilder builder) { builder.RegisterType<SomeMathServiceA>().As<ISomeMathServiceA>(); builder.RegisterType<SomeMathServiceB>().As<ISomeMathServiceB>(); //... more registrations } }
我不知道如何测试它,或者我们是否真的需要测试它.
我尝试过一个单元测试,它接受这个模块并创建一个IContainer并解决每个寄存器依赖,但是一些服务访问DB和配置文件,这些文件在这种情况下非常复杂.
解决方法
(作者)
我想通过单元测试你的意思是“类级单元测试”,其中单元是一个类.如果您想测试IoCModule,您应该使用组件/库级别测试来测试整个库是否正常工作.这(应该)包括IoCModule – 以及库中的所有其他内容.使用此级别的测试达到100%分支覆盖率通常是不可行的,但是此级别级别单元测试的测试组合可以提供非常好的测试可靠性.
我还说最好达到80%的综合覆盖范围而不是只进行阶级单元测试.虽然每个类本身都可以完全按照测试工作,但整体可能无法按预期工作.这就是你应该执行组件级测试的原因.
如何验证类型是否已注册:
现在,如果您仍然坚持执行测试,请不要再看了,您可以这样做:
public class MyModuleTest { private IContainer container; [TestFixtureSetUp] public void TestFixtureSetUp() { var containerBuilder = new ContainerBuilder(); // register module to test containerBuilder.RegisterModule<MyModule>(); // don't start startable components - // we don't need them to start for the unit test this.container = containerBuilder.Build( ContainerBuildOptions.IgnoreStartableComponents); } [TestCaseSource(typeof(TypesExpectedToBeRegisteredTestCaseSource))] public void ShouldHaveRegistered(Type type) { this.container.IsRegistered(type).Should().BeTrue(); } [TestFixtureTearDown] public void TestFixtureTearDown() { this.container.Dispose(); } private class TypesExpectedToBeRegisteredTestCaseSource : IEnumerable<object[]> { private IEnumerable<Type> Types() { // whatever types you're registering.. yield return typeof(string); yield return typeof(int); yield return typeof(float); } public IEnumerator<object[]> GetEnumerator() { return this.Types() .Select(type => new object[] { type }) .GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }
这给出了测试输出,如:
所以每种类型都单独报告.
哇这很容易 – 那又是什么问题呢?
现在在上面的例子中,您可以看到单个(= float)的测试正在通过.现在看一下模块:
public class MyModule : Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<float>(); } }
当我们真正尝试解决浮动时:
container.Resolve<float>();
这是发生的事情:
Autofac.Core.DependencyResolutionException : No constructors on type ‘System.Single’ can be found with the constructor finder ‘Autofac.Core.Activators.Reflection.DefaultConstructorFinder’.
当然,我们可以调整测试以执行Resolve(Type t)而不是使用IsRegistered(Type t) – 但是还有很多其他方法可以使测试通过 – 但是实现失败了.例如:
>绑定类型以使用builder.RegisterInstance< IFoo>(null)>改变生命周期/范围,使其不再正常工作.