3

I know test methods should not see any data except the data created in test context, but when I run the test below, the query returns an org record.

It should not

I have a REST class like

@RestResource(urlMapping='/path/to/*')
global with sharing class MyRest {
    @HttpPost
    global static String executePost(){
        String command = RestContext.request.requestUri.split('/')[3];
        if (command == 'conf')
        {
            return noteConf(RestContext.request.requestBody);
        }
        // irrelevant code here...
    }

private static String noteConf(Blob requestBody){
        String title = 'Check connected app';
        ContentNote[] ln = [Select Id, Title, Content from ContentNote where Title = :title];
        ContentNote n;
        if (ln.size()>0) {
            n = ln[0];
        }
        else{
            n = new ContentNote();
            n.Title = title;
        }
        n.Content = requestBody;
        upsert n;
        return n.Id;
   }

My test method is :

@isTest(seeAllData=false)
    static void test_note(){
        Test.startTest();
        RestRequest req = new RestRequest(); 
        RestResponse res = new RestResponse();
        req.requestURI = '/path/to/conf';
        req.httpMethod = 'POST';
        req.requestBody = Blob.valueOf('the note content !');
        RestContext.request = req;
        RestContext.response= res;
        String s = MyRest.executePost();    //First call, a note should be created
        Id i = (Id) s;    //checks it's an Id (if not an Exception will be thrown)
        String t = MyRest.executePost();    //call it again to check a 2nd note is not created
        System.assertEquals(i, (Id) t);
        Test.stopTest();
    }

I expect the first SOQL query in noteConf method to return 0 record, and the second one to return 1.

But it does

But there already is in my org a ContentNote with title 'Check connected app', the 1st query returns this record. I can't figure out why ?

The seeAllData=false was not there at the beggining, it's the default. Adding it didn't change anything.

Here is the log of the 1st call :

19:01:31.3 (16682032)|SOQL_EXECUTE_BEGIN|[50]|Aggregations:0|SELECT Id, Title, Content FROM ContentNote WHERE Title = :tmpVar1
19:01:31.3 (48338272)|SOQL_EXECUTE_END|[50]|Rows:1
19:01:31.3 (48381399)|HEAP_ALLOCATE|[50]|Bytes:8
19:01:31.3 (48412157)|HEAP_ALLOCATE|[50]|Bytes:329
19:01:31.3 (48547547)|HEAP_ALLOCATE|[50]|Bytes:8
19:01:31.3 (48579122)|VARIABLE_SCOPE_BEGIN|[50]|ln|List<ContentNote>|true|false
19:01:31.3 (48653446)|VARIABLE_ASSIGNMENT|[50]|ln|[{"Id":"0693E000000hfsIQAQ","Title":"Check connected app","LatestContentId":"05T3E000002GTDjUAO","LatestPublishedVersionId":"0683E000000hadgQAA","Content":BLOB(178 bytes)}]|0x26e3554

Wondering if the ContentNote object could have a different behaviour and been always seen, I added this code right after the SOQL query :

Contact[] lc = [Select Id from Contact];
System.debug(lc.size());

which returned 0 while, obviously, there are contacts in my org. That might be a clue...

I checked Salesforce documentation but but did not find anything about that, any help or explanation would be appreciated.

1 Answer 1

5

I know test methods should not see any data except the data created in test context...

This is untrue. Certain types of metadata are exposed in unit tests. Isolation of Test Data from Organization Data in Unit Tests says:

However, objects that are used to manage your organization or metadata objects can still be accessed in your tests such as:

And goes on to list a sampling of objects that ignore database isolation in unit tests, such as ApexClass and User. While ContentNote is not specified on this list, it is apparently one of those types that fall in this category. You will need to delete the record in your unit test in order to then recreate it.

5
  • Thanks sfdcfox for your answer. This is untrue... and also unfalse :). I know some objects are exposed, I'm just surprised that ContentNote is, since it's obviously not related to organization management, and that there's nothing about that feature in documentation. About deleting the object in my test method, I checked that the delete operation was not commited (I'd rather not erase customer's data), and it's not, so your solution is good. As usual. Thanks again. Commented Nov 18, 2020 at 20:08
  • 1
    @EmmanuelBRUNO I only meant to say that should not see any data was untrue in the sense that there are no exceptions, all data is hidden, etc. It is mostly true, but there are many exceptions to this. Modifying data in a unit test is always rolled back, so no need to worry about that.
    – sfdcfox
    Commented Nov 18, 2020 at 20:52
  • Great find, I was not aware of this and could not understand why I was seeing PermissionSet records in my tests.
    – burntsugar
    Commented Jan 13, 2023 at 7:10
  • @sfdcfox Do you know if there is an exhaustive list somewhere of which object types are exposed in unit tests? As you mentioned the SF documentation only lists a handful of examples Commented Mar 10, 2023 at 15:16
  • @soapygopher I've never found an exhaustive list. I'll see if maybe I can come up with such a list, but there's a lot of them.
    – sfdcfox
    Commented Mar 10, 2023 at 15:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .