Java jUnit 中的多个 RunWith 语句
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24431427/
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
Multiple RunWith Statements in jUnit
提问by Hans-Helge
I write unit test and want to use JUnitParamsRunner
and MockitoJUnitRunner
for one test class.
我编写单元测试并想使用JUnitParamsRunner
和MockitoJUnitRunner
用于一个测试类。
Unfortunately, the following does not work:
不幸的是,以下方法不起作用:
@RunWith(MockitoJUnitRunner.class)
@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
// some tests
}
Is there a way to use both, Mockito and JUnitParams in one test class?
有没有办法在一个测试类中同时使用 Mockito 和 JUnitParams?
采纳答案by AlexR
You cannot do this because according to spec you cannot put the same annotation twice on the same annotated element.
您不能这样做,因为根据规范,您不能在同一个带注释的元素上放置两次相同的注释。
So, what is the solution? The solution is to put only one @RunWith()
with runner you cannot stand without and replace other one with something else. In your case I guess you will remove MockitoJUnitRunner
and do programatically what it does.
那么,解决方案是什么?解决办法是只放一个@RunWith()
你不能没有的跑步者,然后用别的东西替换另一个。在您的情况下,我想您将删除MockitoJUnitRunner
并以编程方式执行它的操作。
In fact the only thing it does it runs:
事实上,它唯一能做的就是运行:
MockitoAnnotations.initMocks(test);
in the beginning of test case. So, the simplest solution is to put this code into setUp()
method:
在测试用例的开头。因此,最简单的解决方案是将此代码放入setUp()
方法中:
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
I am not sure, but probablyyou should avoid multiple call of this method using flag:
我不确定,但可能您应该避免使用标志多次调用此方法:
private boolean mockInitialized = false;
@Before
public void setUp() {
if (!mockInitialized) {
MockitoAnnotations.initMocks(this);
mockInitialized = true;
}
}
However better, reusable solution may be implemented with JUnt's rules.
然而,更好的、可重用的解决方案可以使用 JUnt 的规则来实现。
public class MockitoRule extends TestWatcher {
private boolean mockInitialized = false;
@Override
protected void starting(Description d) {
if (!mockInitialized) {
MockitoAnnotations.initMocks(this);
mockInitialized = true;
}
}
}
Now just add the following line to your test class:
现在只需将以下行添加到您的测试类:
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
and you can run this test case with any runner you want.
你可以用任何你想要的跑步者运行这个测试用例。
回答by Erica Kane
As of JUnit 4.7 and Mockito 1.10.17, this functionality is built in; there is an org.mockito.junit.MockitoRule
class. You can simply import it and add the line
从 JUnit 4.7 和 Mockito 1.10.17 开始,这个功能是内置的;有一org.mockito.junit.MockitoRule
堂课。您可以简单地导入它并添加该行
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
to your test class.
到您的测试班。
回答by Valentin Uveges
You can also try this:
你也可以试试这个:
@RunWith(JUnitParamsRunner.class)
public class AbstractTestClass {
// some tests
}
@RunWith(MockitoJUnitRunner.class)
public class DatabaseModelTest extends AbstractTestClass {
// some tests
}
回答by Heungwoo
In my case I was trying to Mock some method in spring bean and
就我而言,我试图在 spring bean 中模拟一些方法和
MockitoAnnotations.initMocks(test);
doesn't works. Instead you have to define that bean to constructed using mock method inside your xml file like following.
不起作用。相反,您必须在 xml 文件中使用模拟方法定义要构造的 bean,如下所示。
...
<bean id="classWantedToBeMocked" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.fullpath.ClassWantedToBeMocked" />
</bean>
...
and add that bean with autowired inside your test class like following.
并在您的测试类中添加自动装配的 bean,如下所示。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="file:springconfig.xml")
public class TestClass {
...
@Autowired
private ClassWantedToBeMocked classWantedToBeMocked;
...
when(classWantedToBeMocked.methodWantedToBeMocked()).thenReturn(...);
...
}
回答by bekce
This solution works for every possible runner, not just this mockito example. For example; for Spring, just change the runner classes and add necessary annotations.
此解决方案适用于所有可能的跑步者,而不仅仅是这个 mockito 示例。例如; 对于 Spring,只需更改跑步者类并添加必要的注释。
@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
@Test
public void subRunner() throws Exception {
JUnitCore.runClasses(TestMockitoJUnitRunner.class);
}
@RunWith(MockitoJUnitRunner.class)
public static class TestMockitoJUnitRunner {
}
}
DatabaseModelTest
will be run by JUnit. TestMockitoJUnitRunner
depends on it (by logic) and it will be run insideof the main in a @Test
method, during the call JUnitCore.runClasses(TestMockitoJUnitRunner.class)
. This method ensures the main runner is started correctly before the static class TestMockitoJUnitRunner
sub-runner runs, effectively implementing multiple nested @RunWith
annotations with dependent test classes.
DatabaseModelTest
将由 JUnit 运行。TestMockitoJUnitRunner
取决于它(通过逻辑),它会运行内部在一个主的@Test
方法在呼叫期间,JUnitCore.runClasses(TestMockitoJUnitRunner.class)
。该方法确保在static class TestMockitoJUnitRunner
子运行器运行之前正确启动主运行器,有效地@RunWith
使用依赖测试类实现多个嵌套注释。
Also on https://bekce.github.io/junit-multiple-runwith-dependent-tests
同样在https://bekce.github.io/junit-multiple-runwith-dependent-tests
回答by lekant
Since the release of PowerMock 1.6, you can do it as easily as
自 PowerMock 1.6 发布以来,您可以像
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(JUnitParamsRunner.class)
public class DatabaseModelTest {
// some tests
}
Explained here https://blog.jayway.com/2014/11/29/using-another-junit-runner-with-powermock/
在这里解释https://blog.jayway.com/2014/11/29/using-another-junit-runner-with-powermock/
回答by Legna
check out this link https://bekce.github.io/junit-multiple-runwith-dependent-tests/using this approach i combined a @RunWith(Parameterized.class) - outer runner - with @RunWith(MockitoJUnitRunner.class) - inner runner. The only tweak i had to add was to make my member variables in the outer class/runner static in order to make them accessible for the inner/nested runner/class. gook luck and enjoy.
查看此链接https://bekce.github.io/junit-multiple-runwith-dependent-tests/使用这种方法我将 @RunWith(Parameterized.class) - 外运行器 - 与 @RunWith(MockitoJUnitRunner.class) -内跑者。我必须添加的唯一调整是将外部类/运行器中的成员变量设为静态,以便内部/嵌套运行器/类可以访问它们。祝你好运,享受。
回答by muni764
I wanted to run SWTBotJunit4ClassRunnerand org.junit.runners.Parameterizedat the same time, I have parametric tests and I want to screenshots when the SWT test fails (the screenshot feature is provided by the SWTBotJunit4ClassRunner). @bekce's answer is great and first wanted go that route but it was either quirky passing through the arguments. Or doing the parametrized in the subclass and loosing the information what exact tests passed/failed and have only the last screenshot (as the screenshot names get the name from the test itself). So either way it was bit messy.
我想同时运行SWTBotJunit4ClassRunner和org.junit.runners.Parameterized,我有参数测试,我想在 SWT 测试失败时截图(截图功能由SWTBotJunit4ClassRunner提供)。@bekce 的回答很棒,而且首先想走那条路,但通过论点是很古怪的。或者在子类中进行参数化并丢失确切测试通过/失败的信息,并且只有最后一个屏幕截图(因为屏幕截图名称从测试本身获得名称)。所以无论哪种方式都有些混乱。
In my case the SWTBotJunit4ClassRunneris simple enough, so I cloned the source-code of the class, gave it my own name ParametrizedScreenshotRunnerand where original was extending the TestRunner, my class is extending the Parameterizedclass so in essence I can use my own runner instead of the previous two. Boiled down my own runner extends on top of Parameterized runner while implementing the screenshot feature on top of it, now my test use this "hybrid" runner and all the tests work as expected straight away (no need to change anything inside the tests).
在我的情况下,SWTBotJunit4ClassRunner很简单,所以我克隆了类的源代码,给它起了我自己的名字ParametrizedScreenshotRunner并且原来扩展了TestRunner,我的类扩展了Parameterized类所以本质上我可以使用我自己的运行器而不是前两个。归结为我自己的跑步者在参数化跑步者之上扩展,同时在其上实现屏幕截图功能,现在我的测试使用这个“混合”跑步者并且所有测试都按预期立即工作(无需在测试中更改任何内容)。
This is how it looks like (for sake of brevity I removed all the comments from the listing):
这是它的样子(为简洁起见,我从列表中删除了所有评论):
package mySwtTests;
import org.junit.runners.Parameterized;
import org.eclipse.swtbot.swt.finder.junit.ScreenshotCaptureListener;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
public class ParametrizedScreenshotRunner extends TestRu Parameterized {
public ParametrizedScreenshotRunner(Class<?> klass) throws Throwable {
super(klass);
}
public void run(RunNotifier notifier) {
RunListener failureSpy = new ScreenshotCaptureListener();
notifier.removeListener(failureSpy); // remove existing listeners that could be added by suite or class runners
notifier.addListener(failureSpy);
try {
super.run(notifier);
} finally {
notifier.removeListener(failureSpy);
}
}
}