使用IoC容器测试工厂方法,在单元测试中需要寄存器类型

时间:2012-04-26 09:52:42

标签: unit-testing inversion-of-control unity-container ioc-container

更新

我想知道工厂是否应该根据方法的用途进行单元测试,因为如果我想测试它,我需要使用IoC容器注册类型,在我的情况下使用Unity。如果我嘲笑工厂,那就不是实际测试工厂方法了。

下面是一个工厂类,它根据参数创建类型实例。

public class CarFactory
    {

        public ICar CreateCar(string CarType)
        {
            ICar Car;

            switch (CarType)
            {
                case RepositoryType.Car1:

                    Car = Ioc.ContainerWrapper.Resolve<Car1>();

                    break;
                case RepositoryType.Car2:       
                    Car = Ioc.ContainerWrapper.Resolve<Car2>();

                    break;

                default:

                    Car = Ioc.ContainerWrapper.Resolve<Car3>();

                    break;

            }

            return Car;
        }

    }


      class Car1 
    {

        private readonly IRepository1 _IRepository1;

        public Car1(IRepository1 repository1)
        {
            _IRepository1 = repository1;

        }
}

3 个答案:

答案 0 :(得分:1)

您必须准备适合此测试的容器(即,Risk类可解析)。根据您当前的实施情况,您无能为力。

当然,这引发了一个问题,即这是否是单元测试,但是我们可以假设统一已经过充分测试并且可以工作(即假设它不会是单元测试的可能失败点)。

在代码中强烈依赖IoC容器的自然缺点。有人可能会说你可以使用自定义抽象包装容器并...并注入它?这感觉不对,我还没有看到有人这样做。

有关相关问题,请参阅this question

答案 1 :(得分:1)

你不能像这样测试:

[SetUp]
public void setup()
{
  // code here to set up the container....
}

[Test]
public void example_test()
{
  var factory = new RiskFactory();
  var risk = factory.CreateGoldRisk("xxxx");
  Assert.True(risk is Risk1);
}

旁注。你有一个IOC容器。一个容器包装,然后包装在工厂中。您的架构可能有太多的抽象层。

答案 2 :(得分:1)

从我的角度来看,你走的是正确的道路。

工厂的目的是创建一个对象,以便允许他们调用服务定位器(是的,您仍在使用服务定位器反模式,但是您正在将其从您的域移动到工厂)

参考:

https://github.com/ninject/ninject.extensions.factory/wiki

回到你原来的问题,我相信你应该测试你的工厂,以保证你得到正确的对象取决于所使用的参数,关于这是单元测试还是任何类型的集成测试存在争议,我的观点是,在Martin Fowler的这篇文章后,它仍然是一个单元测试:

http://martinfowler.com/articles/mocksArentStubs.html#ClassicalAndMockistTesting

这是我测试它的方式:

IRisk myRisk = new RiskFactory().CreateGoldRisk("Risk1");

myRisk.Should().NotBeNull().And.BeOfType<Risk1>();