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 = 'test@test.com';
    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() + 'test2@test.com';
    portalAccountOwner.Alias = 'batman';
    portalAccountOwner.Email = 'bruce.wayne@wayneenterprises.com';
    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;
}
  • 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 Dec 6 '16 at 3:48
  • 3
    Try removing the userRole assignment in the user creation. – Eric Dec 6 '16 at 3:55
  • Updated the assert statements. I've removed the user role, but it did not resolve the issue. – JamesL Dec 6 '16 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 Dec 6 '16 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 Dec 7 '16 at 9:00
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
| improve this answer | |
  • 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 Dec 7 '16 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 Dec 7 '16 at 17:37
  • if you look at the method getPortalUser(), he queries for the contact, etc that he created in static void setupTestData(). – crmprogdev Dec 7 '16 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 Dec 7 '16 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 Dec 7 '16 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.

| improve this answer | |
  • 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 Dec 6 '16 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 Dec 6 '16 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 Dec 7 '16 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 Dec 7 '16 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 Dec 7 '16 at 15:51

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.