在单元测试中自动化依赖注入
本文关键字:依赖 注入 自动化 单元测试 | 更新日期: 2023-09-27 18:11:04
我有一个文件夹,其中的程序集都包含某个接口的实现(每个程序集都不同)。我已经为该接口编写了一些单元测试,并希望在每个实现上自动执行运行接口测试的任务。
我有一个我不喜欢的可行的解决方案:
-
在实际的测试类中编写代码来加载(程序集)并实例化实现,将它们存储在列表中
-
编写每个测试来循环遍历实现列表,在每个实现上运行它的断言。
我想要的是在一个实现上运行所有测试,然后移动到下一个实现上再次运行所有测试,以此类推。我的想法是找到一种方法来做这样的事情(编程):
- 加载程序集并实例化实现-像以前一样,但不在测试类中。
- 创建一个测试类的实例,注入下一个实现。
- 运行测试。
- 移动到下一个实现,重复这个过程。
(我意识到我可以在文件系统中变换文件-例如将程序集放在一个位置>运行加载一个实现的测试>用下一个实现替换程序集,然后重复该过程。但是,如果可能的话,我想要一些不那么粗糙的东西。
我一直在寻找nUnit测试运行器(控制台等)的捷径,但到目前为止还没有找到。有没有人知道,如果有一种方法来实现我想要使用nUnit或任何其他测试套件,可以通过编程控制?或者也许有另一种方法可以满足上面的"我想要什么"标准?
我最终使用了NUnit的SuiteAttribute。
这种方法需要创建一个"伞形类",如下所示:
namespace Validator {
public class AllTests {
[Suite]
public static IEnumerable Suite {
get {
var directory = @"[ImplementationAssembliesPath]";
var suite = new ArrayList();
// GetInstances is a method responsible for loading the
// assemblys and instantiating the implementations to be tested.
foreach (var instance in GetInstances(directory)) {
suite.Add(GetResolvedTest(instance));
}
return suite;
}
}
// This part is crucial - this is where I get to inject the
// implementations to the test.
private static Object GetResolvedTest(ICalculator instance) {
return new CalculatorTests {Calculator = instance};
}
[...]
}
注意,测试类有一个属性,用于注入我想要的实现。我之所以选择属性注入,是因为测试运行者通常不喜欢默认构造函数。然而,我不得不从实际的测试类(此处省略)中删除TestFixtureAttribute
,以避免混淆Console-Runner要运行什么。
/fixture
参数的NUnit控制台运行器:
namespace TestRunner {
using System;
using NUnit.ConsoleRunner;
internal class Program {
private static void Main(String[] args) {
var testDllPath = @"[TestAssemblyPath]/Validator.dll";
var processArgument = @"/process=Separate";
var domainArgument = @"/domain=Multiple";
var runtimeArgument = @"/framework=4.5";
var shadowArgument = @"/noshadow";
var fixtureArgument = String.Format(@"/fixture={0}", "[Namespace].AllTests");
Runner.Main(new[] {
testDllPath,
processArgument,
domainArgument,
runtimeArgument,
shadowArgument,
fixtureArgument
});
Console.ReadLine();
}
}
}
我仍然很想听听你对这件事的看法,以及其他解决方案。
如果你想测试一组固定的程序集,你不需要做一些花哨的事情,比如移动程序集或指示测试运行程序。
与普通类一样,您可以对单元测试类使用继承。我建议您创建一个抽象基类来完成测试该接口实现的繁重工作。对于接口的每个实现,都可以创建一个继承基类的新类。基类可以像这样:
public class BaseMyInterfaceImplementationTest
{
protected MyInterface ClassUnderTest;
//Add your tests here with the [Test] attribute:
[Test]
public void TestScenario1()
{
//do your test on ClassUnderTest
}
}
和这样的派生类:
[TestFixture]
public class Implementation1Tests : BaseMyInterfaceImplementationTest
{
[SetUp]
public void BaseTestInitialize()
{
ClassUnderTest = new Implementation1();
}
}