在单元测试中使用依赖注入对象是不错的主意吗?

时间:2015-12-14 12:17:56

标签: testing dependency-injection nunit

我不确定我所做的事实上是用DI进行单元测试的“正确”方式。现在我要求我的ViewModelLocator实际创建我需要的所有实例,然后获取我需要测试的实例,这使得测试单个实例非常简单,因为我们假设Receipt需要创建一个Reseller对象,经销商需要要创建的User对象,用户需要创建一些其他对象,这将创建一个对象链来创建,以便测试单个实例。

使用di usally接口将被模拟并解析为您想要创建的对象,但是简单的Entities / ViewModels呢?

使用DI进行单元测试的最佳做法是什么?

 public class JournalTest
{
    private ReceiptViewModel receipt;
    private ViewModelLocator locator;
    [SetUp]
    public void SetUp()
    {
        locator = new ViewModelLocator();

        receipt = SimpleIoc.Default.GetInstance<ReceiptViewModel>();
    }
    [TearDown]



    [Test]
    public void CheckAndCreateNewJournal_Should_Always_Create_New_Journal()
    {
        receipt.Sale.Journal = null;
        receipt.Sale.CheckAndCreateNewJournal();
        Assert.NotNull(receipt.Sale.Journal);
    }

}

2 个答案:

答案 0 :(得分:3)

首先,您没有在代码中使用依赖注入。你所拥有的是服务定位器(服务定位器创建与IoC /服务定位器的紧密耦合并使其难以测试)。

是的,它很糟糕(Service Locator和Dependency Injection),因为它意味着:你没有进行UnitTest,你正在进行集成测试。

在您的情况下,ReceiptViewModel不会单独测试,但您的测试也会测试ReceiptViewModel的依赖关系(即存储库,注入的服务等)。这称为集成测试。

UnitTest必须只测试有问题的类和无依赖性。您可以通过存根(依赖项的虚拟实现,假设您已将接口用作依赖项)或使用模拟(使用Moq等模拟框架)来实现此目的。

这更容易/更好,因为您不必实现整个类,但只需为您知道的测试用例所需的方法设置模拟。

作为附加说明,您必须自己创建实体。根据您的UnitTest框架,可能有数据驱动的测试(通过测试方法上的属性)或者您只是在代码中创建它们,或者如果您在许多类中使用模型/实体,则为它创建一个辅助方法。

视图模型不应该被注入到构造函数中(至少要避免),因为它会紧密地耦合它们

答案 1 :(得分:1)

单元测试应该快速运行并且应该是确定性的。这意味着你必须模拟/存储破坏这两个规则的所有内容。

模拟/存根依赖的最佳方法是注入它们。在生产中,类由DI框架组装,但在单元测试中,您应该手动组装它们并在需要时注入模拟。

还有一种经典的单元测试方法,您可以在其中存根/模拟您的类的每个依赖项,但它没有用,因为您没有获得任何东西。 Martin Fowler写了一篇很棒的文章:link 您还应该阅读不断增长的面向对象软件:以测试为导向。吨有用的知识。