junit测试用例

bq3bfh9z  于 2021-07-12  发布在  Java
关注(0)|答案(3)|浏览(432)

我有一个下等生。我是新来写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;

    }
}
cczfrluj

cczfrluj1#

首先有两件事:
为什么加载状态是静态的?基本上,这个类的两个示例将使用相同的加载状态变量。加载状态应该不是静态的,或者checkloadingstatus也应该是静态的。
加载状态被命名为。如果你想让它保持静态,你应该把它命名为loading\u status。如果它不是静态的,我们就把它命名为loadingstatus。这就是java惯例。
您应该为加载\u状态创建一个正确的枚举类型,而不是整数。 while (loading_status == IN_PROGRESS); 只是不好的做法。至少你能做的是: 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);
}
// ...

最后,我想有些东西会把加载状态更新为completed之类的。我猜你也在用同步的。如果加载发生在两个不同的线程上,那么您将陷入死锁。如果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
nnt7mjpx

nnt7mjpx2#

您的私有方法根据内部私有变量loading\u 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依赖项:
e、 g.Maven

<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-api-mockito</artifactId>
  <version>1.6.4</version>
</dependency>
68bkxrlz

68bkxrlz3#

通常,当您无法测试您的代码时,您应该考虑重写它,以便它是可测试的。私有方法不能在类外以常规方式调用,甚至不能在junit测试中调用。
您可以做一些事情使其可测试:
重写代码以将方法拆分为更小的方法。在适当的情况下,应始终这样做。
您可以将方法包设为私有的(删除私有修饰符),这样您的测试类(必须在同一个包中)就可以访问它。
您可以使方法受到保护,这样您就可以在测试中继承类,并在继承的类上间接调用该方法。
你可以调用一个方法,这个方法调用了这个方法,你想测试并做出相应的Assert。
如果您倾向于将方法的可见性更改为包私有或受保护,则可以将方法注解为 @VisibleForTesting ,所以像sonar和其他团队成员这样的工具知道,为什么它不是私有的。
希望有帮助。

相关问题