Oma*_*lfi 7 c# unit-testing code-coverage autofac
我们有一个核心库,可以进行复杂的计算,我们认为它很关键,我们希望在该库上有100%的代码覆盖率.我们现在有96%这是伟大的,但由于这个类我们不能得到100%:
public class IoCModule : Autofac.Module
{
protected override void Load(Autofac.ContainerBuilder builder)
{
builder.RegisterType<SomeMathServiceA>().As<ISomeMathServiceA>();
builder.RegisterType<SomeMathServiceB>().As<ISomeMathServiceB>();
//... more registrations
}
}
Run Code Online (Sandbox Code Playgroud)
我不知道如何测试它,或者我们是否真的需要测试它.
我尝试过一个单元测试,它接受这个模块并创建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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以每种类型都单独报告.
现在在上面的例子中,您可以看到single(= float)的测试正在通过.现在看一下模块:
public class MyModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<float>();
}
}
Run Code Online (Sandbox Code Playgroud)
当我们真正尝试解决时float:
container.Resolve<float>();
Run Code Online (Sandbox Code Playgroud)
这是发生的事情:
Autofac.Core.DependencyResolutionException:可以使用构造函数查找器'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'找到类型'System.Single'上的构造函数.
当然,我们可以调整测试来执行Resolve(Type t)而不是使用IsRegistered(Type t)- 但是还有很多其他方法可以使测试通过 - 但是实现失败了.例如:
builder.RegisterInstance<IFoo>(null)我终于找到了一种方法来测试它.autofac模块有一个方法Configure,用于注册组件.我就这样做了:
public class CheckRegistrations
{
[Test]
public void Should_Have_Register_Types()
{
//Arrange
var typesToCheck = new List<Type>
{
typeof (ISomeMathServiceA),
typeof (ISomeMathServiceB)
};
//Act
var typesRegistered = this.GetTypesRegisteredInModule(new IoCModule());
//Arrange
Assert.AreEqual(typesToCheck.Count, typesRegistered.Count());
foreach (var typeToCheck in typesToCheck)
{
Assert.IsTrue(typesRegistered.Any(x => x == typeToCheck), typeToCheck.Name + " was not found in module");
}
}
private IEnumerable<Type> GetTypesRegisteredInModule(Module module)
{
IComponentRegistry componentRegistry = new ComponentRegistry();
module.Configure(componentRegistry);
var typesRegistered =
componentRegistry.Registrations.SelectMany(x => x.Services)
.Cast<TypedService>()
.Select(x => x.ServiceType);
return typesRegistered;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8008 次 |
| 最近记录: |