代码之家  ›  专栏  ›  技术社区  ›  jpoh

以具体类作为返回类型的单元测试工厂方法

  •  33
  • jpoh  · 技术社区  · 17 年前

    question 我可以验证返回的接口是否是我期望的特定具体类型。

    如果工厂返回具体类型,我应该检查什么(因为目前不需要使用接口)?目前我正在做如下工作:

    [Test]
    public void CreateSomeClassWithDependencies()
    {
        // m_factory is instantiated in the SetUp method
        var someClass = m_factory.CreateSomeClassWithDependencies();
    
        Assert.IsNotNull(someClass);
    }
    

    问题是 Assert.IsNotNull 似乎有些多余。

    public SomeClass CreateSomeClassWithDependencies()
    {
        return new SomeClass(CreateADependency(), CreateAnotherDependency(),
                             CreateAThirdDependency());
    }
    

    我想确保我的工厂方法正确地设置了所有这些依赖项。那么,没有其他方法来实现这些依赖关系吗 public/internal 然后在单元测试中检查哪些属性?(我不太喜欢修改测试科目以适应测试)

    编辑:在回答Robert Harvey的问题时,我使用NUnit作为我的单元测试框架(但我没有想到它会有太大的不同)

    5 回复  |  直到 9 年前
        1
  •  37
  •   Mark Seemann    17 年前

    通常,创建可用于基于状态的测试的公共属性没有错。是:这是您为启用测试场景而创建的代码,但它是否会损害您的API?是否可以想象其他客户以后会发现同样的财产有用?

    特定于测试的代码和测试驱动的设计之间有一条细线。我们不应该引入除了满足测试需求之外没有其他潜力的代码,但是引入遵循普遍接受的设计原则的新代码是完全可以的。我们让测试 驾驶 我们的设计-这就是为什么我们称之为TDD:)

    在我看来,向一个类添加一个或多个属性以使用户更好地检查该类通常是一件合理的事情,因此我认为您不应该忽略引入此类属性。

    除此之外,我支持纳德的回答:)

        2
  •  25
  •   Nader Shirazie    17 年前

    如果工厂返回具体类型,并且您保证工厂总是返回具体类型,并且不为null,那么不,没有 在测试中有很多价值。它确实允许您确保,随着时间的推移,不会违反此期望,并且不会抛出异常之类的事情。

    这种测试方式只是确保,当您在未来进行更改时,您的工厂行为不会在您不知情的情况下发生更改。

    如果您的语言支持反射,那么对于依赖项,可以使用反射。这并不总是最容易维护的,并且将测试与实现紧密地结合在一起。你必须决定这是否可以接受。这种方法往往非常脆弱。

    但是您似乎真的试图将构造的类与调用构造函数的方式区分开来。您最好使用DI框架来获得这种灵活性。

    通过 new -根据需要整理所有类型,您不会给自己太多接缝(接缝是一个您可以在程序中改变行为而无需在该位置进行编辑的地方)。

    CreateADependency() , CreateAnotherDependency() 和 CreateAThirdDependency() CreateSomeClassWithDependencies() ,你可以 感觉 是否创建了正确的依赖项。

        3
  •  3
  •   Robert    17 年前

    我们所做的是用工厂创建依赖性,并且在测试运行时使用依赖性注入框架来替代模拟工厂。然后,我们对这些模拟工厂设定了适当的期望值。

        4
  •  3
  •   Sam Saffron James Allen    17 年前

    你总是可以用反射来检查东西。没有必要仅仅为了单元测试而公开某些内容。我发现我很少需要进行反思,这可能是一个糟糕设计的迹象。

    看看您的示例代码,是的,Assert not null看起来是多余的,这取决于您设计工厂的方式,有些将从工厂返回null对象,而不是排除。

        5
  •  0
  •   Jonathan    9 年前

    据我所知,您希望测试依赖项是否正确构建并传递给新实例?

    @Test
    public void CreateSomeClassWithDependencies()
    {
        dependencyFactory = context.mock(DependencyFactory.class);
        classAFactory = context.mock(ClassAFactory.class);
    
        myDependency0 = context.mock(MyDependency0.class);
        myDependency1 = context.mock(MyDependency1.class);
        myDependency2 = context.mock(MyDependency2.class);
        myClassA = context.mock(ClassA.class);
    
        context.checking(new Expectations(){{
           oneOf(dependencyFactory).createDependency0(); will(returnValue(myDependency0));
           oneOf(dependencyFactory).createDependency1(); will(returnValue(myDependency1));
           oneOf(dependencyFactory).createDependency2(); will(returnValue(myDependency2));
    
           oneOf(classAFactory).createClassA(myDependency0, myDependency1, myDependency2);
           will(returnValue(myClassA));
        }});
    
        builder = new ClassABuilder(dependencyFactory, classAFactory);
    
        assertThat(builder.make(), equalTo(myClassA));
    }
    

    (如果无法模拟ClassA,可以使用new为myClassA分配非模拟版本)