简体   繁体   English

JUnit测试是否可以通过iff方法实现正确且递归的方法?

[英]Is there a way for a JUnit test to pass iff method implementation is correct AND recursive?

I am setting up some practical exams and require implementation of certain methods to be recursive. 我正在设置一些实践考试,并要求某些方法的实现是递归的。 Is there a way for the JUnit test to pass only if the implementation of the method is recursive (and correct, of course)? 是否只有在方法的实现是递归的(当然是正确的)的情况下,JUnit测试才能通过?

I have tried using getStackTrace() but I couldn't find a way to get the methods calls made earlier in the program. 我已经尝试过使用getStackTrace()但是我找不到方法来获取程序前面的方法调用。 (Because if I can do that, I can check if containsDigit in the following example is being called the required number of times) (因为我可以这样做,所以我可以检查以下示例中的containsDigit是否被调用了所需的次数)

MWP MWP

import static org.junit.Assert.*;
import org.junit.*;
import java.io.*;
import java.text.*;
import java.util.*;
import org.junit.rules.*;
import java.lang.reflect.*;

public class Service { //begin class 
    /**
     * @param n: assumed to be more than 0
     * @param d, d >= 0 and d <= 9
     * @return true if number n contains the digit d, false otherwise
     * you may assume that 0 itself doesn't contain ANY digit (not even 0)
     * NOTE: This method must be implemented recursively.
     * hint: n%10 gives the last digit, n/10 gives the rest of the number
     */
    public static boolean containsDigit(int n, int d) {
        return false; //to be completed
    }

    @Test
    public void testContainsDigit() {
        assertTrue(Service.containsDigit(1729, 1));
        assertTrue(Service.containsDigit(1234567890, 2));
        assertFalse(Service.containsDigit(1729, 8));
    }
}

I would like the test to pass for a recursive implementation like: 我希望测试通过递归实现,例如:

    public static boolean containsDigit(int n, int d) {
        if(n == 0) 
            return false;
        if(n%10 == d)
            return true;
        return containsDigit(n/10, d);
    }

and fail for an iterative (even if correct) implementation like: 并无法进行迭代(即使正确)的实现,例如:

    public static boolean containsDigit(int n, int d) {
        while(n > 0) {
            if(n%10 == d) {
                return true;
            }
            n/=10;
        }
        return false;
    }

Any help, or guidance in the right direction would very much be appreciated. 任何帮助或正确方向的指导将不胜感激。

JUnit itself doesn't have tools to check whether the flow is recursive or iterative, but it can certainly check that the call returns correct results. JUnit本身没有工具来检查流是递归的还是迭代的,但是可以肯定地检查调用是否返回正确的结果。

Now its also impossible to gather stacktraces from "earlier" executions. 现在也不可能从“较早的”执行中收集堆栈跟踪。

I don't see how mocks can help you here neither, but I might be missing something, maybe our colleagues will provide an example for this, however I suggest the following approach: 我看不到模拟在这里也无法为您提供任何帮助,但是我可能会遗漏一些东西,也许我们的同事会为此提供一个示例,但是我建议采用以下方法:

  • Don't require method to be static, instead require the methods to be regular. 不需要方法是静态的,而是要求方法是常规的。

Then use the following trick: 然后使用以下技巧:

Prepare the following class but don't provide it to the students (I've assumed that this is for educational purposes since you've talked about exams, sorry if I'm wrong) who are expected to implement the "Service" class: 准备以下课程,但不要将其提供给希望实施“服务”课程的学生(我认为这是出于教育目的,因为您已经谈论过考试,如果我错了,抱歉)。

 class MyServiceForChecks extends Service {
      private List<StackTraceElement[]> invocationStackTraces = new ArrayList<>(); 

      public boolean containsDigit(int n, int d) { // its not static anymore
           StackTraceElement [] stackTrace =  getStackTrace();
           invocationStackTraces.add(stackTrace); 
        return super.containsDigit(n,d);
      }

      public List<StackTraceElement[]> getInvocationStackTraces () {
           return this.invocationStackTraces;
      }
 }

In JUnit test the MyServiceForChecks class instead of Service class. 在JUnit中,测试MyServiceForChecks类而不是Service类。 After the containsDigits method finishes the execution you can call getInvocationStackTraces method and analyze the result. containsDigits方法完成执行后,可以调用getInvocationStackTraces方法并分析结果。

If you have cannot create MyServiceForChecks class, you can generate it dynamically with CGLIB library. 如果无法创建MyServiceForChecks类,则可以使用CGLIB库动态生成它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM