[SalesForce] why need seeAllData = true in test class when use connectAPI

In my controller i'm using connectApi and my class functionality is working fine but the issue is when i'm using in my Test class (SeeAllData=true) it's covered 100% but seeAllData = true is not considering in best practice what the alternate to avoid seeAllData true.

without seeAllData true its throw an error System.UnsupportedOperationException: ConnectApi methods are not supported in data siloed tests. Please use @IsTest(SeeAllData=true).

Best Answer

The alternative to using seeAllData=true is applying a mocking or delegate pattern so that the Connect API is not called in test context, but you can still validate behavior. Here's a simple and very explicit example (no StubProvider):

public class PostsToChatter {
    public interface ChatterPoster {
        void postToChatter(Id parentRecord, String text);
    }

    @TestVisible private class RealChatterPoster implements ChatterPoster {
        public void postToChatter(Id parentRecord, String text) {
            if (!Test.isRunningTest()) callConnectAPIHere(parentRecord, text);
            // Note that if we keep this minimal (one line) we still obtain full code coverage even though the Connect API call does not actually go through.
        }
    }

    @TestVisible private ChatterPoster myPoster;


    // ... constructors and code ...

    public PostsToChatter() {
        // Add a default delegate (the real Chatter poster class
        myPoster = new RealChatterPoster();
    }

    public void doSomethingRequiringAChatterPost() {
        // ... stuff happens ...
        myPoster.postToChatter(someId, someText);
    }
}

Then, in test context, we have the freedom to inject a completely different class that implements PostsToChatter.ChatterPoster, but doesn't really call the Connect API. Meanwhile, we've kept our actual-Chatter delegate so tiny and simple that we can still call it in test context to get the code coverage, even though we can't validate its behavior like we ought to.

@isTest
public static class PostsToChatter_TEST {
    private class MockChatterPoster implements PostsToChatter.ChatterPoster {
        public Id expectedId;
        public String expectedString;
        public Integer timesCalled = 0;

        public void postToChatter(Id parentRecord, String text) {
            System.assertEquals(expectedId, parentRecord, 'correct parent');
            System.assertEquals(expectedString, text, 'correct post body');
            timesCalled++;
        }
    }

    @isTest
    public static void testTheClass() {
        PostsToChatter p = new PostsToChatter();
        p.myPoster = new MockChatterPoster();

        // ... invoke class functionality...

        System.assertEquals(1, p.myPoster.timesCalled, 'chatter post called');
        // Post contents validated in the mock - or do it here if preferred.
    }
}
Related Topic