[英]Junit Test Case for private method
我有以下课程。 我是编写 junit 测试的新手。 我需要为此编写测试用例。 如何在测试类中为startSchemaMaintenance方法编写测试方法,因为它正在调用没有参数的私有方法?
public class SchemaMaintenance {
//Loading statuses overview
// NOT_STARTED = 0
// START_LOADING = 1
// IN_PROGRESS = 2
// COMPLETED = 3
// LOADING_ERROR = 4
private static volatile Integer loading_status = 0;
public void startSchemaMaintenance() throws Exception {
if (checkLoadingStatus() == 1) {
doSchemaMaintenance();
loading_status = 3;
}
}
private void doSchemaMaintenance(){
//Do something....
}
private int checkLoadingStatus() throws Exception {
if (loading_status==0 ||loading_status == 2) {
synchronized (loading_status) {
if (loading_status==0) {
loading_status = 2;
return 1;
}else if(loading_status == 2) {
while(loading_status == 2);
if((loading_status == 4)){
throw new Exception("status = " + 4);
}
}else if(loading_status == 4) {
//log.error(generateErrorMessage());
throw new Exception("status = " + 4);
}
}
}else if((loading_status == 4)){
//log.error(generateErrorMessage());
throw new Exception("status = " + 4 );
}
return loading_status;
}
}
首先有几点:
while (loading_status == IN_PROGRESS);
只是不好的做法。 至少你可以做的是: while(loading_status == IN_PROGRESS) { Thread.sleep(100); };
while(loading_status == IN_PROGRESS) { Thread.sleep(100); };
然而,超时是更好的做法。 类似的东西:long timeoutMillis = 5000L; // Should come from a configuration or something
long endTimeMillis = System.currentTimeMillis() + timeoutMillis;
while (loadingStatus == IN_PROGRESS) {
long remainingMillis = end - System.currentTimeMillis();
if (remaining <= 0) {
// Timeout while loading
loadingStatus = LOADING_ERROR;
break;
}
Thread.sleep(50);
}
// ...
最后,我猜有些事情会将 loadingStatus 更新为已完成或其他内容。 我猜你也在那里使用同步。 如果加载发生在 2 个不同的线程上,那么您最终将陷入死锁。 如果 checkLoadingStatus 先进入同步块,那么当加载完成时加载线程将永远无法进入同步块,因为 checkLoadingStatus 正在保持锁。
最后但并非最不重要的是回答你的问题,如果你想保持你的方法私有,你可以通过反射调用它,但这又是一种不好的做法。 通常,您应该避免对私有方法进行单元测试,并对调用它的方法进行单元测试。 但是,如果您确实需要对特定方法进行单元测试,请将其设为包私有而不是私有,然后您可以在包含您的方法的类所在的同一个包中创建单元测试。 并且您可以向该方法添加注释,说明它仅对单元测试可见。 在这种情况下您的代码结构示例:
src
+-- main
+-- +-- com/app/MyClass.java
+-- test
+-- com/app/MyClassTest.java // this test class will able to access package-private methods in MyClass
通常,当您无法测试您的代码时,您应该考虑重写它,使其可测试。 私有方法不能以常规方式在您的类之外调用,甚至不能在 JUnit 测试中调用。
您可以做一些事情来使其可测试:
重写您的代码以将方法拆分为更小的方法。 应始终在适当的情况下进行。
您可以将方法包设为私有(删除私有修饰符),以便您的测试类(必须在同一个包中)可以访问它。
您可以使方法受保护,因此您可以在测试中继承您的类,并通过继承的类间接调用该方法。
您可以调用一个方法,该方法调用该方法,您想测试并相应地做出断言。
如果您倾向于将方法的可见性更改为包私有或受保护,您可以将您的方法注释为@VisibleForTesting
,以便像 Sonar 和其他团队成员这样的工具知道为什么它不是私有的。
希望能帮助到你。
您的私有方法根据内部私有变量loading_status值工作,因此在您的测试中,您应该能够更改该变量。 为此,您可以执行以下操作:
package com.test
import com.test.SchemaMaintenance;
import org.junit.Test;
import org.mockito.internal.util.reflection.Whitebox;
public class SchemaMaintenanceTest {
@Test
public void TestSchema() throws Exception {
SchemaMaintenance schema = new SchemaMaintenance();
Whitebox.setInternalState(schema,"loading_status",2);
schema.startSchemaMaintenance();
}
}
假设您应该在项目中包含mockito依赖项:
例如 Maven
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.4</version>
</dependency>
这是一种对我有用的方法。
根据所需的方法和内部类等的访问,会有不同的变化。
这个例子不能有静态“测试器”,因为我们需要测试非静态内部类中的方法。
// Outer owner class
//
public class OwnerClass Class {
private class InnerClass {
:
// method I'm testing
//
private void doSomething)( String name ){
...
}
}
:
// Tester class
//
public class InnerClassTester {
private final InnerClass innerClass = new InnerClass();
:
// test invocatiion
//
private void doSomething)( String name ){
innerClass.doSomething)( name )
}
}
// Get an instance of the tester
//
public InnerClassTester getInnerClassTester() {
return new InnerClassTester();
}
在你的单元测试里面......
@Test
public void doSomethingTest() throws Exception {
OwnerClass ownerClass = new OwnerClass();
innerClassTester = ownerClass.InnerClassTester();
:
// Test the private method
//
innerClassTester.doSomething( "123456" );
}
与调试器一起使用。 您需要根据您的访问灵活地定义测试器和测试器获取器。 测试仪也可能受到protected
,我没有尝试过。 一切顺利。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.