java 如何避免 JUnit 测试用例中的继承?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6715281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 16:59:22  来源:igfitidea点击:

How to avoid inheritance in JUnit test cases?

javajunit

提问by yegor256

I have a number of test cases in JUnit. All of them need the same code to be executed in their @BeforeClassstatic method. It's a code duplication and I'm trying to get rid of it. A dirty way of doing this is by inheritance. Are there any other mechanisms in JUnit, that may help?

我在 JUnit 中有许多测试用例。它们都需要在它们的@BeforeClass静态方法中执行相同的代码。这是一个代码重复,我正试图摆脱它。这样做的一种肮脏方式是通过继承。JUnit 中是否还有其他机制可能会有所帮助?

PS. I wrote this blog post about this very subject: http://www.yegor256.com/2015/05/25/unit-test-scaffolding.html

附注。我写了这篇关于这个主题的博客文章:http: //www.yegor256.com/2015/05/25/unit-test-scaffolding.html

回答by eskatos

The JUnit way to compose reusable code (instead of inheriting from it) are Rules.

编写可重用代码(而不是从它继承)的 JUnit 方法是规则。

See https://github.com/junit-team/junit/wiki/Rules

https://github.com/junit-team/junit/wiki/Rules

Here is a dumb sample, but you'll get the point.

这是一个愚蠢的示例,但您会明白这一点。

import org.junit.rules.TestRule;
import org.junit.runners.model.Statement;
import org.junit.runner.Description;

public class MyTestRule implements TestRule {
  @Override
  public Statement apply(final Statement statement, Description description) {
    return new Statement() {
      public void evaluate() throws Throwable {
        // Here is BEFORE_CODE
        try {
          statement.evaluate();
        }?finally {
          // Here is AFTER_CODE
        }
      }
    };
  }
}

You can then use your TestRule like this:

然后,您可以像这样使用您的 TestRule:

import org.junit.Rule;

public class MyTest {
    @Rule
    public MyTestRule myRule = new MyTestRule();
}

BEFORE_CODE and AFTER_CODE will then be executed around each of your test methods.

然后将围绕您的每个测试方法执行 BEFORE_CODE 和 AFTER_CODE。

If you need to run your code only once per class, use your TestRule as a @ClassRule:

如果您需要为每个类只运行一次代码,请将您的 TestRule 用作 @ClassRule:

import org.junit.ClassRule;

public class MyTest {
    @ClassRule
    public static MyTestRule myRule = new MyTestRule();
}

Now, BEFORE_CODEand AFTER_CODEwill be executed around each of your test class.

现在,BEFORE_CODEAFTER_CODE将围绕每个测试类的执行。

@Rulefield is not static, @ClassRulefield is.

@Rule字段不是静态的,@ClassRule字段是。

A @ClassRule can be declared in a Suite too.

@ClassRule 也可以在 Suite 中声明。

Note that you can declare several rules in a single test class, that's how you compose test lifecycles at test-suites, test-classes and test-methods levels.

请注意,您可以在单个测试类中声明多个规则,这就是您在测试套件、测试类和测试方法级别组成测试生命周期的方式。

A Rule is an object that you instanciate in your test classes (statically or not). You can add contructor parameters if needed.

规则是您在测试类中实例化的对象(静态或非静态)。如果需要,您可以添加构造函数参数。

HTH

HTH

回答by Suraj Chandran

If the method is some kind of utility, then separate it out to a different class with a static method and call that method in your @BeforeClass.

如果该方法是某种实用程序,则使用静态方法将其分离到不同的类,并在您的@BeforeClass 中调用该方法。

I emphasize on the fact that don't use inheritance just because it solves your problem, use it when doing so creates sense in your class hierarchy.

我强调一个事实,不要仅仅因为它解决了你的问题就使用继承,这样做时使用它会在你的类层次结构中产生意义。

回答by Marcin Michalski

You may create test runner

您可以创建测试运行程序

public class MyTestRunner extends BlockJUnit4ClassRunner {
  @Override
  protected Object createTest() throws Exception {
     Object test = super.createTest();
     doStuff();
  }

  public void doStuff(){
     //common code
  }
}


@RunWith(MyTestRunner.class)
public class MyTest1{
    @Test
    public void test1(){
      //test method
    }
}

回答by Cedric Beust

There is absolutely nothing wrong with inheritance in this case, it's actually the only way to avoid repeating this code in each subclass. The fact that @BeforeClass methods have to be declared static in JUnit is unfortunate, but that shouldn't stop you. Extend the class and you have the initialization code automatically run for you without having to do anything.

在这种情况下继承绝对没有错,它实际上是避免在每个子类中重复此代码的唯一方法。不幸的是,@BeforeClass 方法必须在 JUnit 中声明为静态,这一事实令人遗憾,但这不应阻止您。扩展类,您可以自动为您运行初始化代码,而无需执行任何操作。

回答by Ryan Stewart

Static methods aren't inherited, so inheritance isn't an option by default. If you mean you're moving the method to a common parent class, then that seems a poor choice since you only get one parent in Java. A test support class of some sort would seem more appropriate. It's also possible that you're seeing a need for a parameterized test.

静态方法不会被继承,因此默认情况下继承不是一个选项。如果您的意思是将方法移至公共父类,那么这似乎是一个糟糕的选择,因为在 Java 中您只能获得一个父类。某种测试支持类似乎更合适。您也可能看到需要参数化 test

回答by u290629

I think if the classes has "is-a"relation, inheritance is reasonable.

我认为如果类具有“is-a”关系,继承是合理的。

If the base class is MyBeforeClasswhich defines @BeforeClassmethod, and MyTestClass1"is-a" MyBeforeClass, MyTestClass1 extends MyBeforeClassis OK.

如果基类是MyBeforeClass定义@BeforeClass方法的,并且MyTestClass1"is-a" MyBeforeClassMyTestClass1 extends MyBeforeClass则可以。

回答by James Kingsbery

Depending on the nature of the setup code, you can potentially put all your tests in a test suiteand have the setup code run there. The downside to this is that you cannot run tests individually (since the test depends on the setup code).

根据设置代码的性质,您可以将所有测试放在一个测试套件中,并在那里运行设置代码。这样做的缺点是您不能单独运行测试(因为测试取决于设置代码)。

回答by Ray Toal

If each and every class needs to have a @BeforeClassannotated method that is exactlythe same as every other, then inheritance does not feel thatwrong to me. If each of these initializing methods simply share somecode, you could make a TestUtilclass with some shared behavior and make calls to this shared behavior from each of the @BeforeClassmethods.

如果每类都需要有一个@BeforeClass注解的方法是完全相同一样每隔,然后继承不觉得我错了。如果这些初始化方法中的每一个都只是共享一些代码,那么您可以创建一个TestUtil具有一些共享行为的类,并从每个@BeforeClass方法调用这个共享行为。

回答by Michael Piefel

It is test code, and it is not meant for heavy re-use. Do not over-engineer. Do not apply all the design patterns that you know. For test code, the rules are different.

它是测试代码,不适合大量重用。不要过度设计。不要应用您知道的所有设计模式。对于测试代码,规则不同。