1

I have created a service which allows a portal user to query records based on some values set up on their own contact record.

In my test scenario, I want to set up something similar, where I first create a contact, create a portal user associated with that contact, runAs that user, then call that service.

However, upon executing the code, while the contact record for the portal user does indeed have an ID, no records are retrieved in a generic contact query. There's relatively little documentation on how to create a portal user, never mind interacting with the portal user's contact record.

Any insight on the reason why no contact records can be access would be greatly appreciated.

Code snippet below:

public testMethod static void testService()
{
    User u;

    System.runAs(getNonPortalUserWithRole())
    {
        setupTestData();
        u = getPortalUser();
    }

    List<Contact> y = [
        SELECT id, Offering_Project__c, Region__c
        FROM Contact
        WHERE id = :u.contactid
    ];
    System.assertNotEquals(0, y.size(), 'No contact records found');

    System.runAs(u)
    {
        System.assertEquals(u.Id, UserInfo.getUserId(), 'Running user is not the portal User.');

        User x = [
            SELECT id, contactid, contact.Offering_Project__c, contact.Region__c
            FROM User
            WHERE id = :UserInfo.getUserId()
        ];
        System.assertNotEquals(null, x.contactid, 'Portal User contact is null');

        List<Contact> c = [
            SELECT id, Offering_Project__c, Region__c
            FROM Contact
            //WHERE id = :x.contactid
        ];
        System.assertNotEquals(0, c.size(), 'No contact records found'); // Fails here.
    }
}

static void setupTestData()
{
    Account a = new Account();
    a.name = 'TEST';
    a.bkrAccount_Status__c = 'Active';
    insert a;
    a.isPartner = true;
    update a;
    a = [
        SELECT id, recordTypeId, bkrAccount_Status__c
        FROM Account
        WHERE id = :a.Id
    ];
    System.debug('!!! ' + a);

    Contact c = new Contact();
    c.AccountId = a.Id;
    c.LastName = 'TEST';
    c.Email = '[email protected]';
    c.bkrContact_Status__c = 'Active';
    c.Offering_Project__c = 'TEST OFFERING';
    c.Region__c = 'TEST REGION';
    insert c;
    c = [
        SELECT id, Offering_Project__c, Region__c, recordTypeId, bkrContact_Status__c
        FROM Contact
        WHERE id = :c.Id
    ];
    System.debug('!!! ' + c);
}

private static User getNonPortalUserWithRole()
{
    UserRole nonPortalRole = [
        Select Id
        FROM UserRole
        Where PortalType = 'None'
        Limit 1
    ];
    System.debug('UserRole is ' + nonPortalRole);

    Profile adminProfile = [
        SELECT Id
        FROM Profile
        WHERE name = 'System Administrator'
    ];
    User portalAccountOwner = new User();
    portalAccountOwner.UserRoleId = nonPortalRole.Id;
    portalAccountOwner.ProfileId = adminProfile.Id;
    portalAccountOwner.Username = System.now().millisecond() + '[email protected]';
    portalAccountOwner.Alias = 'batman';
    portalAccountOwner.Email = '[email protected]';
    portalAccountOwner.EmailEncodingKey = 'UTF-8';
    portalAccountOwner.Firstname = 'Bruce';
    portalAccountOwner.Lastname = 'Wayne';
    portalAccountOwner.LanguageLocaleKey = 'en_US';
    portalAccountOwner.LocaleSidKey = 'en_US';
    portalAccountOwner.TimeZoneSidKey = 'America/Chicago';
    insert portalAccountOwner;

    return portalAccountOwner;
}

/*
 * Returns portal user.
 */
private static User getPortalUser()
{
    Profile p = [
        SELECT Id
        FROM Profile
        WHERE Name = 'TEST PROFILE'
        LIMIT 1
    ];

    UserRole ur = [
        SELECT id
        FROM UserRole
        WHERE Name = 'TEST USER ROLE'
        LIMIT 1
    ];

    Contact c = [
        SELECT id
        FROM Contact
        WHERE LastName = 'TEST'
        LIMIT 1
    ];

    User u = new User();
    u.FirstName = 'TEST';
    u.LastName = 'TEST';
    u.Alias = u.FirstName + '_' + u.LastName;
    u.Email = u.FirstName + '.' + u.LastName + '@test.com';
    u.Username = u.FirstName + '.' + u.LastName + '@test.com';
    u.CommunityNickname = u.FirstName + '_' + u.LastName;
    u.TimeZoneSidKey = 'America/Los_Angeles';
    u.LocaleSidKey = 'en_US';
    u.LanguageLocaleKey = 'en_US';
    u.isActive = true;
    u.EmailEncodingKey = 'UTF-8';
    u.ProfileId = p.Id;
    u.ContactId = c.Id;
    u.userRole = ur;
    insert u;

    u = [
        SELECT id, contactId, IsPortalEnabled, User.Profile.UserLicense.Name
        FROM User
        WHERE id = :u.id
    ];
    System.debug('!!! ' + u);

    return u;
}
6
  • Just a note, your third parameter on the asserts should be a helpful error message not a description of what the assert should do. If it fails it would be confusing to the running user
    – Eric
    Commented Dec 6, 2016 at 3:48
  • 3
    Try removing the userRole assignment in the user creation.
    – Eric
    Commented Dec 6, 2016 at 3:55
  • Updated the assert statements. I've removed the user role, but it did not resolve the issue.
    – JamesL
    Commented Dec 6, 2016 at 14:14
  • 3
    Because when creating a portal user a portal role will be assigned if user has no role. Without the portal role they will not have access to the account and contact. IIRC. All examples of creating portal users do not set role.
    – Eric
    Commented Dec 6, 2016 at 14:16
  • the only thing I can think of is permissions. Are you sure your portal user has the right permissions to query contacts?
    – Novarg
    Commented Dec 7, 2016 at 9:00

2 Answers 2

2

The following works in my org with regards to a Partner Portal (Legacy) Not sure exactly what type of portal you are using but this passed for me:

  1. Account OWD Private - Profile has read, create, edit on account

Test class

@isTest
private with sharing class PortalCheck_Tests {

    private static testmethod void basicTest() {

        User u = [Select ID From User where id = :userInfo.getUserID()];

        User portalUser;

        system.runAs(u){
            portalUser = createPartnerUser();
        }

        system.runAs(portalUser){

            Contact[] c = [Select ID From contact where Id = :protalUser.ContactId];
            Contact[] c2 = [Select ID From contact];

            system.assertNotEquals(true,c2.isEmpty());
            system.assertNotEquals(true,c.isEmpty());

        }
    }


    private static User createPartnerUser(){
        Profile p = [Select ID, Name from Profile Where Name = 'Portal Profile'];

        Map<String,Schema.RecordtypeInfo> aRtMap = Account.sObjectType.getDescribe().getRecordtypeinfosbyname();

        Account a = New Account(Recordtypeid = aRTMap.get('Partner').getRecordtypeid(), Name = 'TestPortalAccount');
        insert a;

        Contact c = New Contact(FirstName = 'Portal', LastName = 'Test', AccountID = a.id);
        insert c;

        user u = New User(
            UserName = 'test_' + math.random() + '@test.com',
            FirstName = 'Test-First',
            LastName = 'Test-Last',
            Alias = 'test',
            email = 'test' + math.random() + '@test.com',
            CommunityNickName = string.valueOf(math.random()).substring(0,6),
            ProfileID = p.id,
            TimeZoneSidKey = 'America/New_York', 
            LocaleSidKey = 'en_US', 
            EmailEncodingKey = 'UTF-8', 
            LanguageLocaleKey = 'en_US',
            ContactID = c.id

            );

        insert u;

        return u;

    }


}

Try using this code and see if you can get this to pass then adjust as necessary. If it still does not work then it is definitely a config issue.

Couple of questions:

  1. Is this a customer portal or partner portal you are working with? Although not sure it makes a difference.
  2. What is the license type of the user you are creating? Gold Partner, High Volume, etc
6
  • In his 1st comment below my answer, he stated it is a Partner Portal. He doesn't show the code he's testing, but it appears he's trying to query the user he creates. It does appear he's trying to create a Partner Portal User but hasn't said which license he's using. Note that the account is set for isPartner = true. If I'm not mistaken, Partner Portal licenses work much like Community Plus licenses where the use of Apex Managed Sharing is frequently necessary in order to share a contact with Portal Users.
    – crmprogdev
    Commented Dec 7, 2016 at 15:49
  • @crmprogdev - In the OP code he is creating the user via u = getPortalUser(); and in the org I tested I do not see any sharing rules with the user I am creating in my test but I could have missed it. AlL I can say is the above code works and if it does not for the OP then it is defiantly a sharing issue.
    – Eric
    Commented Dec 7, 2016 at 17:37
  • if you look at the method getPortalUser(), he queries for the contact, etc that he created in static void setupTestData().
    – crmprogdev
    Commented Dec 7, 2016 at 17:59
  • @crmprogdev - He still inserts the new user. Creating the contact and account as the running user. Same thing I am doing just abstracted out a bit into two methods...but essentially the same. Or I can be completely missing something. Either way, we know the OP code does not work, I am just providing a starting point for code that is known to work and doing essentially the same thing.
    – Eric
    Commented Dec 7, 2016 at 18:02
  • @crmprogdev - Did not mean to....I removed the first part of the comment after rereading it realizing it sounded that way....apologies
    – Eric
    Commented Dec 7, 2016 at 18:07
0

It appears to me the main reason your test is failing is because you're not assigning an email address to the contact in your static void setup() method. Inserting that contact will fail without an email address (required field for a contact).

I'll add that it appears from your code that you're creating Partner Portal users. In order to do that, you really need to be using a RunAs() user in your test setup method who has the appropriate profile and role for that. Contrary to what others have suggested, Partner Portal Users do have Roles.

Generally speaking, in most portals, the Portal User somewhat inherits their Role from their Owner. It depends on the type of Portal. A Partner Portal is MUCH different than a Customer Portal, so you may need to directly assign their role if the User is a Partner. If you're creating a Customer Portal User inside of a Partner Portal, that user would not have a Role.

5
  • The email field isn't necessarily required. The assert statement after querying User x passes without issue, which means that the contact ID is inserted and assigned without issue. We are indeed creating and testing Partner Portal users. You can safely assume that the test runner, a user with admin rights, will also be creating the portal users in the application.
    – JamesL
    Commented Dec 6, 2016 at 15:30
  • The email IS required for all contacts and I see you've edited your code to add it. It appears you're trying to access the portal RunAs user's contact info which they may not have access to since they don't own their contact record. This is a sharing issue that you've not provided for. The Owner of that record is the RunAs User who created the Portal RunAs user in your test class. That's about all I can tell you since you've not shown us the class you're testing or all of your test class code for that matter.
    – crmprogdev
    Commented Dec 6, 2016 at 17:35
  • 1
    @crmprogdev - by default email is not a required field for the contact. It may be customized that way but not out of the box. It is required for a user though.
    – Eric
    Commented Dec 7, 2016 at 0:06
  • 1
    N.B. Contact.Email is not required as otherwise how could SFDC be used to keep track of people who don't have computers -- like, say, an application for keeping track of prisoners where the contact info is a cell (not mobile phone) number :-)
    – cropredy
    Commented Dec 7, 2016 at 1:49
  • I researched this and couldn't find where it was required even though it's always been in every org I've worked in. Perhaps it's because email address is always used a primary externalId for a Contact that I came to believe this. I yield to Eric and Cropredy on this one. Thank you for the lesson guys. Based on the limited information available, I suspect his issue is one of sharing.
    – crmprogdev
    Commented Dec 7, 2016 at 15:51

You must log in to answer this question.

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