How can I make spock execute another method at runtime using the Annotation extension?

First, if there is an easier way to solve this problem, here is a diagram of what I'm trying to accomplish. I want to annotate my testing methods using the KnownIssue annotation (extension AbstractAnnotationDrivenExtension), which takes the defect identifier as a parameter and checks the status of the defect before running the tests. If the defect is fixed, it will continue to execute if it is not fixed. I want him to ignore the test, but if it is closed or deleted, I want to cause a logging test error, stating that the test should be deleted or updated, and the annotation has been deleted since the defect is now closed or deleted.

Everything works for me until a testing error is triggered. What I tried does not work:

  • Throwing an exception in the visitFeatureAnnotation method, which causes a crash due to which all tests after this fail.
  • Creating a class that extends Spec and includes a test method that registers the message and fails, then tried to use feature.featureMethod.setReflection () to set the method to execute in another way. In this case, I get java.lang.IllegalArgumentException: the object is not an instance of the class declaration
  • Then I tried using ExpandoMetaClass to add the method directly to declaringClass, and point feature.featureMethod.setReflection point to it, but I still get the same IllegalArgumentException.

Here is what I have in my visitFeatureAnnotation method for my last attempt:

def myMetaClass = feature.getFeatureMethod().getReflection().declaringClass.metaClass myMetaClass.KnownIssueMethod = { -> return false } feature.featureMethod.setReflection(myMetaClass.methods[0].getDoCall().getCachedMethod()); 

Any other ideas on how I could do this, and either cause the test to fail, or replace the method with another that won't work?

+6
source share
1 answer

Good ... Finally, I came up with a solution. Here is what I got. As part of the visitFeatureAnnotation method, I add the created CauseFailureInterceptor.

Here is the complete source, if anyone is interested, just requires you to extend KnownIssueExtension and implement the abstract getDefectStatus method:

 public abstract class KnownIssueExtension extends AbstractAnnotationDrivenExtension<KnownIssue> { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(KnownIssueExtension.class) public void visitFeatureAnnotation(KnownIssue knownIssue, FeatureInfo feature) { DefectStatus status = null try{ status = getDefectStatus(knownIssue.value()) } catch(Exception ex){ LOGGER.warn("Unable to determine defect status for defect ID '{}', test case {}", knownIssue.value(), feature.getName()) // If we can't get info from Defect repository, just skip it, it should not cause failures or cause us not to execute tests. } if (status != null){ if(!status.open && !status.fixed){ LOGGER.error("Defect with ID '{}' and title '{}' is no longer in an open status and is not fixed, for test case '{}'. Update or remove test case.", knownIssue.value(), status.defectTitle, feature.getName()) feature.addInterceptor(new CauseFailureInterceptor("Defect with ID '" + knownIssue.value() + "' and title '" + status.defectTitle + "' is no longer in an open status and is not fixed, for test case '" + feature.getName() + "'. Update or remove test case.")) }else if (status.open && !status.fixed){ LOGGER.warn("Defect with ID '{}' and title '{}' is still open and has not been fixed. Not executing test '{}'", knownIssue.value(), status.defectTitle, feature.getName()) feature.setSkipped(true) }else if (!status.open && status.fixed){ LOGGER.error("Defect with ID '{}' and title '{}' has been fixed and closed. Remove KnownIssue annotation from test '{}'.", knownIssue.value(), status.defectTitle, feature.getName()) feature.addInterceptor(new CauseFailureInterceptor("Defect with ID '" + knownIssue.value() + "' and title '" + status.defectTitle + "' has been fixed and closed. Remove KnownIssue annotation from test '" + feature.getName() + "'.")) }else { // status.open && status.fixed LOGGER.warn("Defect with ID '{}' and title '{}' has recently been fixed. Remove KnownIssue annotation from test '{}'", knownIssue.value(), status.defectTitle, feature.getName()) } } } public abstract DefectStatus getDefectStatus(String defectId) } public class CauseFailureInterceptor extends AbstractMethodInterceptor{ public String failureReason public CauseFailureInterceptor(String failureReason = ""){ this.failureReason = failureReason } @Override public void interceptFeatureExecution(IMethodInvocation invocation) throws Throwable { throw new Exception(failureReason) } } class DefectStatus{ boolean open boolean fixed String defectTitle } 
+1
source

Source: https://habr.com/ru/post/984342/


All Articles