0

After some research I found that is not possible to test your flow in a test class.

Test ControllerExt for Flow and https://techman97.wordpress.com/2013/10/18/flow-and-finishlocation/

My logic heavily depends on the result that is returned from the flow. So I am able to only get up to 50% test coverage. The resources I have been reading are from a few years ago so I was hoping there was something more up to date on testing flows and finish locations. Does anyone have any ideas on how to input a value for my instance of my flow?

test class:

@IsTest
public with sharing class FlowToWebservice_RedirectTest {
  public static testMethod void test1() {
    FlowToWebservice_Redirect ftws = new FlowToWebservice_Redirect(new ApexPages.StandardController(new Opportunity()));
    ftws.getFinishPage2();
    ftws.getCRID();
    ftws.getOPPID();
  }
}

vfp:

<apex:page id="CreditReviewControllerPage" standardController="Opportunity" tabStyle="Opportunity" extensions="FlowToWebservice_Redirect">
    <flow:interview name="CRC_1_UILayer" interview="{!aFlow2}" finishLocation="{!FinishPage}">
        <apex:param name="inputOpptyId" value="{!Opportunity.Id}"/>
    </flow:interview>
</apex:page>

redirect logic:

global class FlowToWebservice_Redirect {
  public Flow.Interview.CRC_1_UILayer aFlow2 {get; set;}

  public PageReference getFinishPage(){
    if (aFlow2==null) {
        PageReference p = new PageReference('/' + currentPg);
        p.setRedirect(true);
        return p;
    }
    else {
        if (aFlow2.varprocessstepresult == 'STOP') {
            PageReference p = new PageReference('/' + getOPPID());
            p.setRedirect(true);
            return p;
        }
        else {
            PageReference p = new PageReference('/' + getCRID());
            p.setRedirect(true);
            return p;
        }
    }
  }
}

because aflow2 will always be null, I am only able to cover the first condition.

  • 1
    Verifying that your code works as you expect it to work is the most important part of unit testing. It’s also one of the things that Force.com developers commonly neglect. Unit tests that do not verify the results of the code aren’t true unit tests. They are commonly referred to as smoke tests, which aren’t nearly as effective or informative as true unit tests. - How to Write Good Unit Tests – Adrian Larson Sep 27 '17 at 17:41
  • @AdrianLarson, I have tested and verified that my code works as expected – Olivia Sep 27 '17 at 17:57
  • 1
    you seem to have missed the point of my comment. If you write a unit test and it does not contain any assertions, your automated test suite isn't doing what it's supposed to. – Adrian Larson Sep 27 '17 at 18:18
  • yes, I do need to add in system.asserts. But I am not even able to get to the point of asserting a value. I will add them in but I still need to achieve the coverage over the flow before I can assert that it has a value (other then null) – Olivia Sep 27 '17 at 18:32
2

Have you tried setting the variable in your test class to any valid value? You can get a valid value using System.debug in a non-text context, then either using a json string to create an instance of the object with the field values set, or set the values yourself when creating an instance of that object (something you probably can't do with a flow).

(Disclaimer: I don't work much with flows, but I have used these methods to create test data for other objects which are difficult/impossible to create in test contexts)

For example:

@IsTest
public with sharing class FlowToWebservice_RedirectTest {
  public static testMethod void test1() {
    FlowToWebservice_Redirect ftws = new FlowToWebservice_Redirect(new ApexPages.StandardController(new Opportunity()));

    ftws.aFlow2 = /** Some Valid value **/;

    // Or, if you have a JSON String of a valid object 
    ftws.aFlow2 = JSON.deserialize('/** Seralized Value **/', Type.forName('Flow.Interview'));

    ftws.getFinishPage2();
    ftws.getCRID();
    ftws.getOPPID();
  }
}

Alternatively, you could use a mocking pattern:

@testVisible 
private static String mock_ProcessResult { get; set; } 

public static String getProcessResult() {
    if (Test.IsRunningTest()) {
        return mock_ProcessResult; 
    } else {
        return aFlow2.varprocessstepresult; 
    }
}

Then, in your test class:

@IsTest
public with sharing class FlowToWebservice_RedirectTest {
  public static testMethod void test1() {
    FlowToWebservice_Redirect ftws = new FlowToWebservice_Redirect(new ApexPages.StandardController(new Opportunity()));

    ftws.mock_ProcessResult = 'STOP';

    ftws.getFinishPage2();
    ftws.getCRID();
    ftws.getOPPID();
  }
}

Adding in a assertions in your code is also very important- a method may execute without causing an exception, and still fail to work as expected (such as returning incorrect data, or setting the wrong fields, for example).

For example:

PageReference returnedPage = ftws.getFinishPage2();

System.assertEquals(true, returnedPage.getRedirect()); 
System.assertEquals('/' + someTestId, returnedPage.getUrl()); 

If you would like to use a mocking framework, I'd suggest the ApexMock Framework.

| improve this answer | |
  • I have tried setting the aflow2 to a value and I always get the same error message Error: Illegal assignment from String to flow.Interview.CRC_1_UILayer or if I try to instantiate a new flow with preset values I get Error: Constructor not defined: [Flow.Interview.CRC_1_UILayer].<Constructor>(). I then try setting the constructor and I am rejected as well. The mocking patter helped up my lines of test coverage but not for the flow coverage. It just covered the instantiated object. – Olivia Sep 27 '17 at 18:31
  • N.B. ApexMocks is a more advanced mocking pattern (based on Mockito) and avoids putting Test.isRunningTest() into PROD code. – cropredy Sep 28 '17 at 0:00
  • Github link. Thanks for adding a name to the conversation, I'll make an edit to include a reference to a real framework. Hopefully this example serves as a good starting point. – battery.cord Sep 28 '17 at 13:15
  • @cropredy and battery.cord, thank you for these suggestions. I am trying to avoid using ApexMocks but it is looking bleak. I we need to deploy this week and I don't think I will have time to review and implement. I found this article that is from 2013 but he suggests to just rework my original code. What are your thoughts on that? kevindjohnson.wordpress.com/2013/08/30/… – Olivia Sep 29 '17 at 17:06
0

I am aware this is not best practice, and if I am being honest I am not sure if it will even deploy to prod. I will be testing this later today. But I found a way to get 100% test coverage without having to add mock data or use ApexMocks.

I rearranged my code so that the uncovered lines were on the same line as the covered lines. See attachment. I wouldn't advise using this method if you have another option or have more time to implement ApexMocks, this was a last minute work around. I will update later today if I am actually able to deploy with this method.

100% coverage work around

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.