从测试类调用测试类的非默认构造函数

Posted

技术标签:

【中文标题】从测试类调用测试类的非默认构造函数【英文标题】:Calling non default constructor of tested class from test class 【发布时间】:2014-10-05 09:16:22 【问题描述】:

我是单元测试的新手,我想知道这是怎么回事,我猜这是典型的,通常可以解决的问题: 我有要测试的受保护方法。我已经用测试类覆盖了测试类,但是测试类的构造函数有 4 个参数,没有默认构造函数。您在测试类的哪个部分添加了对基(4 个参数)构造函数的调用?我试过[SetUp] 方法,但我得到Use of keyword 'base' is not valid in this context 错误。

我认为这个简单的案例是自我解释,但这里是例子:

public class A

    protected Class1 obj1;
    protected Class2 obj2; 
    protected Class3 obj3; 
    protected Class4 obj4;

    public A(Class1 obj1, Class2 obj2, Class3 obj3, Class4 obj4)
    
        this.obj1 = obj1;
        this.obj2 = obj2;
        this.obj3 = obj3;
        this.obj4 = obj4;
    

    protected virtual void MethodA()
    
        //some logic
    


[TestFixture]
public class ATests : A

    [SetUp]
    public void SetUp()
                
        this.obj1 = Substitute.For<Class1>();
        this.obj2 = Substitute.For<Class2>();
        this.obj3 = Substitute.For<Class3>();
        this.obj4 = Substitute.For<Class4>();
        //this line below doesn't compile with the `Use of keyword 'base' is not valid in this context` error.
        base(obj1, obj2, obj3, obj4);
    

    [Test]
    public void MethodA_test()
    
        //test MethodA logic
    

【问题讨论】:

请提供一些代码来证明您的问题。 另一个你可能感兴趣的问题***.com/questions/5601730/… 【参考方案1】:

ATests 不应继承自 A

只需将您的测试类定义更改为

[TestFixture]
public class ATests

然后代替

base(obj1, obj2, obj3, obj4);

做一些类似的事情

this.globalA = new A(obj1, obj2, obj3, obj4);

其中globalAA 类型的私有字段,您可以在测试中使用它。


要访问protected 方法,您可以将您的测试项目作为friend assembly 添加到您的主项目中,并将您的protected 方法标记为protected internal

【讨论】:

但是如何调用受保护的A.MethodA? @kobac 请参阅我上面的评论,您不应该测试受保护(或私有)方法。您应该测试功能。这可以完全使用公共成员来完成。 @Bryan 我不同意这一点 - 测试对公众隐藏的方法通常很有意义,出于意识形态原因将自己限制在公共方法似乎很愚蠢。 @dav_i:所谓的public只会调用你组件上的public方法。您的组件只会调用其他组件的公共方法。公共合同是唯一会被调用的东西。除了不幸的设计决策、低质量的遗留代码或奇怪的第 3 方要求之外,您永远不需要测试公共合同以外的任何东西。 @jimmy_keen 考虑这样一种情况,您生成一个带有public abstract class 的框架,您希望客户端继承该框架,其中包含protected 方法,显然可以在派生类中调用。这些protected 方法仍然是与您的客户签订的合同的一部分,因此需要与实际的public 方法一样多地进行测试。【参考方案2】:

常见且简单的方法是创建从 A 派生的类,该类将公开您要测试的受保护成员:

public class TestableA : A

    public void TestableMethodA() 
    
        base.MethodA();
    

现在,您的测试夹具将改为执行TestableA。您实际上并没有从 A 派生测试夹具,您只需在测试中使用新派生的仅测试类:

[TestFixture]
public void ATests

    [Test]
    public void MethodA_DoesSomethingImportant()
    
        var testedComponent = new TestableA();
        testedComponent.TestableMethodA();
        // verify 
    

这种方法的缺点是需要创建额外的类型仅用于测试目的。这可以通过模拟框架使用(和使用模拟调用基本实现)来缓解。当其他一切都失败或最终变得昂贵时,为了单元测试目的而改变方法的可见性纯粹应该是最后的手段。

【讨论】:

以上是关于从测试类调用测试类的非默认构造函数的主要内容,如果未能解决你的问题,请参考以下文章

C++关于类结构体大小和构造顺序析构顺序的测试。

C++关于类结构体大小和构造顺序析构顺序的测试。

java怎么调用带参数构造函数

Java:没有默认构造函数的类的newInstance

C++调用父类的构造函数规则

子类为啥要调用父类的构造函数