Java 如何确定代码是否在 JUnit 测试中运行?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2341943/
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
How can I find out if code is running inside a JUnit test or not?
提问by Dr. Max V?lkel
In my code I need to do certain fixes only when it is run inside a JUnit test. How can I find out if code is running inside a JUnit test or not? Is there something like JUnit.isRunning() == true ?
在我的代码中,只有在 JUnit 测试中运行时,我才需要进行某些修复。如何确定代码是否在 JUnit 测试中运行?有没有类似 JUnit.isRunning() == true 的东西?
采纳答案by Janning
It might be a good idea if you want to programmatically decide which "profile" to run. Think of Spring Profiles for configuration. Inside an integration tests you might want to test against a different database.
如果您想以编程方式决定运行哪个“配置文件”,这可能是个好主意。考虑使用 Spring Profiles 进行配置。在集成测试中,您可能希望针对不同的数据库进行测试。
Here it the tested code that works
这是经过测试的有效代码
public static boolean isJUnitTest() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
List<StackTraceElement> list = Arrays.asList(stackTrace);
for (StackTraceElement element : list) {
if (element.getClassName().startsWith("org.junit.")) {
return true;
}
}
return false;
}
回答by SOA Nerd
If you're doing things differently because you're doing a unit test you're defeating the purpose of a unit test. A unit test is supposed to perform exactly like production would (except for the setup and teardown of any necessary data and such you need....but that is included in the JUnit test itself and not your code).
如果您因为进行单元测试而以不同的方式做事,那么您就违背了单元测试的目的。单元测试应该像生产一样执行(除了任何必要数据的设置和拆卸以及您需要的数据......但这包含在 JUnit 测试本身而不是您的代码中)。
However, if you truly do have a good reason for this I'd look at the stack and see if JUnit is there.
但是,如果您确实有充分的理由这样做,我会查看堆栈并查看 JUnit 是否存在。
回答by Thilo
First of all, this a probably not a good idea. You should be unit testing the actual production code, not slightly different code.
首先,这可能不是一个好主意。您应该对实际的生产代码进行单元测试,而不是稍微不同的代码。
If you really want to do this, you could look at the stacktrace, but since you are changing your program for this anyway, you might just as well introduce a new static boolean field isUnitTesting
in your code, and have JUnit set this to true. Keep it simple.
如果您真的想这样做,您可以查看堆栈跟踪,但由于您正在为此更改程序,您不妨isUnitTesting
在代码中引入一个新的静态布尔字段,并让 JUnit 将其设置为 true。把事情简单化。
回答by Jaime Saiz
I can find a justification for this, which is when you want to provide code in a production class to help testing. This would be similar to the Java assert, which only applies when the debug flag is set.
我可以找到一个理由,那就是当您想在生产类中提供代码来帮助测试时。这将类似于 Java 断言,它仅在设置了调试标志时适用。
Something like this:
像这样的东西:
Object debugState() {
// This is only meant to be called when testing
if (!JUnit.isRunning()) {
throw new IllegalStateException("Not in a test!");
}
// Now compute possibly costly debug information
// not to be used in production
Object state = ...
}
回答by user3022950
Lots of people on this thread say that it's a bad idea for code to run slightly differently while under JUnit. I generally agree, but I think there are some exceptions.
这个线程上的很多人都说,在 JUnit 下运行稍微不同的代码是一个坏主意。我大体上同意,但我认为也有一些例外。
For example, I am currently writing INTEGRATION (as opposed to Unit) tests for an app that connects to a DB.
例如,我目前正在为连接到数据库的应用程序编写集成(而不是单元)测试。
These acceptance tests often need to completely reinitialize the DB with specific test data.
这些验收测试通常需要使用特定的测试数据完全重新初始化数据库。
Obviously, I don't want this EVER, EVER to be done on an actual production DB, because that might completely erase valuable production data.
显然,我不希望在实际生产数据库上执行此操作,因为这可能会完全删除有价值的生产数据。
The easiest way to guarantee that this will never happen, is to make it impossible for the code to connect to a production DB when it is running under JUnit. This in turn can be done if, for example, the Factory that generates a connection can tell that it's running under JUnit, and in that case, will return a null connection unless the database we are trying to connect to has a name that is known to be a test database (ex: "testdatabase").
保证这种情况永远不会发生的最简单方法是,在 JUnit 下运行时,使代码无法连接到生产数据库。例如,如果生成连接的工厂可以告诉它在 JUnit 下运行,那么这反过来可以完成,在这种情况下,除非我们尝试连接的数据库具有已知名称,否则将返回空连接成为测试数据库(例如:“testdatabase”)。
回答by Milanka
When using Spring one can define a bean which holds this value.
使用 Spring 时,可以定义一个保存此值的 bean。
In application context:
在应用程序上下文中:
@Bean
public boolean isRunningTests() {
return false;
}
In test application context:
在测试应用程序上下文中:
@Bean
public boolean isRunningTests() {
return true;
}
Inject the value to a Spring component:
将值注入 Spring 组件:
@Resource
private boolean isRunningTests;
private void someMethod() {
if (isRunningTests()) {
....
回答by tux_mind
this is not strictly related to the user question, but I'm pretty sure that someone that get there may find it useful.
这与用户问题并不严格相关,但我很确定到达那里的人可能会发现它很有用。
I use the following approach: expose a package-local constructor that will be used from tests.
我使用以下方法:公开一个将在测试中使用的包本地构造函数。
e.g.
例如
src/main/java/ApplicationService.java
src/main/java/ApplicationService.java
public class ApplicationService {
private final Integer someInternalObject;
public ApplicationService(String somePublicArgument) throws NumberFormatException {
someInternalObject = Integer.valueOf(somePublicArgument, 16);
}
ApplicationService(Integer someInternalObject) {
this.someInternalObject = someInternalObject;
}
}
src/test/ApplicationServiceTest.Java
src/test/ApplicationServiceTest.Java
public class ApplicationServiceTest {
@Test
public void testSomething() throws Exception {
ApplicationService applicationService = new ApplicationService(0);
}
}
expose it to all tests
将其暴露给所有测试
not final classes
不是期末班
Extend it in the tests and provide a public constructor for the package-local or protected one.
在测试中扩展它并为包本地或受保护的包提供一个公共构造函数。
final classes
期末班
Make a public Factory Methodin the same package ( within tests ) that will create it using the package-local constructor.
在将使用包本地构造函数创建它的同一个包(在测试中)中创建一个公共工厂方法。
回答by Snickers3192
How about checking if the junit jar is in the classpath?
如何检查 junit jar 是否在类路径中?
回答by Meir G.
In order to distinguish between test and no test you can always define special property or value in application-test.properties.
为了区分测试和无测试,您始终可以在 application-test.properties 中定义特殊属性或值。
回答by Robert Va?an
The shortest (least code) solution is to have a global flag that is set when tests are notrunning. You can then set it once in your main()
(or similar entry point) instead of setting it repeatedly in setup methods of all test classes. This will work as long as there is no other way to enter the code (no alternate main
).
最短(最少代码)的解决方案是在测试未运行时设置一个全局标志。然后您可以在您的main()
(或类似的入口点)中设置一次,而不是在所有测试类的设置方法中重复设置它。只要没有其他方法可以输入代码(没有备用main
),这就会起作用。
The second shortest solution is to scan the call stack for junit package like in Janning's answer. This will work as far as junit doesn't hide itself behind another library and an executor.
第二个最短的解决方案是像Janning's answer一样扫描 junit 包的调用堆栈。只要 junit 不会将自己隐藏在另一个库和执行程序后面,这就会起作用。
Dependency injection will work too, but in this case it's just a fancy way to set what's essentially a global flag.
依赖注入也可以工作,但在这种情况下,它只是一种设置本质上全局标志的奇特方式。