+ Start a Discussion
awilawil 

Bug in SFDC-provided test method for MyProfilePageController.cls

With Winter '11, if you create a Site, a new Salesforce-provided class gets deployed to your org: MyProfilePageController.cls

 

There is test code in this class that fails if you don't have a portal user installed. This prevents you from doing anything in that org that requires running all tests.

 

Here is the error:

 

System.QueryException: List has no rows for assignment to SObject

Class.MyProfilePageController.testSave: line 78, column 35 External entry point

 

and the line in question:

 

 

User existingPortalUser = [SELECT id, profileId, userRoleId FROM User WHERE UserRoleId <> null AND UserType='CustomerSuccess' LIMIT 1];

 

This failure prevents doing any save from Eclipse. You can't deploy new code, edit object metadata files, etc. Complete showstopper.

 

Can anyone:

 * confirm this (we think reproducing will require that you create a new Site, perhaps the first Site in the org, after Winter 11)

 * think of a work-around (tried enabling self-service portal, but it doesn't create the required user type)

 

Anyone from Salesforce confirm that this is a bug and not something we're doing wrong?

 

Thanks!

 

Here is the entire class:

 

/**
 * An apex class that keeps updates of a portal user in sync with its corresponding contact.
   Guest users are never able to access this page.
 */
public class MyProfilePageController {

    private User user;
    private boolean isEdit = false;
    
    public User getUser() {
        return user;
    }

    public MyProfilePageController() {
        user = [SELECT id, email, username, usertype, communitynickname, timezonesidkey, languagelocalekey, firstname, lastname, phone, title,
                street, city, country, postalcode, state, localesidkey, mobilephone, extension, fax, contact.email
                FROM User
                WHERE id = :UserInfo.getUserId()];
        // guest users should never be able to access this page
        if (user.usertype == 'GUEST') {
            throw new NoAccessException();
        }
    }
    
    public Boolean getIsEdit() {
        return isEdit;
    }
    
    public void edit() {
        isEdit=true;
    }    
    
    public void save() {
        if (user.contact != null) {              
            setContactFields(user.contact);
        }
        
        try {
            update user;
            if (user.contact != null) { 
                update user.contact;
            }
            isEdit=false;
        } catch(DmlException e) {
            ApexPages.addMessages(e);
        }
    }
    
    public PageReference changePassword() {
        return Page.ChangePassword;
    }
    
    public void cancel() {
        isEdit=false;
        user = [SELECT id, email, username, communitynickname, timezonesidkey, languagelocalekey, firstname, lastname, phone, title,
                street, city, country, postalcode, state, localesidkey, mobilephone, extension, fax, contact.email
                FROM User
                WHERE id = :UserInfo.getUserId()];
    }
    
    private void setContactFields(Contact c) {
        c.title = user.title;
        c.firstname = user.firstname;
        c.lastname = user.lastname;
        c.email = user.email;
        c.phone = user.phone;
        c.mobilephone = user.mobilephone;
        c.fax = user.fax;
        c.mailingstreet = user.street;
        c.mailingcity = user.city;
        c.mailingstate = user.state;
        c.mailingpostalcode = user.postalcode;
        c.mailingcountry = user.country;
    }

    static testMethod void testSave() {         
        // Modify the test to query for a portal user that exists in your org
        User existingPortalUser = [SELECT id, profileId, userRoleId FROM User WHERE UserRoleId <> null AND UserType='CustomerSuccess' LIMIT 1];
        System.assert(existingPortalUser != null, 'This test depends on an existing test portal user to run');
        
        String randFax = Math.rint(Math.random() * 1000) + '5551234';
        
        System.runAs(existingPortalUser) {
            MyProfilePageController controller = new MyProfilePageController();
            System.assertEquals(existingPortalUser.Id, controller.getUser().Id, 'Did not successfully load the current user');
            System.assert(controller.isEdit == false, 'isEdit should default to false');
            controller.edit();
            System.assert(controller.isEdit == true);
            
            controller.cancel();
            System.assert(controller.isEdit == false);
            
            controller.getUser().Fax = randFax;
            controller.save();
            System.assert(controller.isEdit == false);
        }
        
        // verify that the user and contact were updated
        existingPortalUser = [Select id, fax, Contact.Fax from User where id =: existingPortalUser.Id];
        System.assert(existingPortalUser.fax == randFax);
        System.assert(existingPortalUser.Contact.fax == randFax);
    }

}

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
Ryan-GuestRyan-Guest

The salesforce.com team technology team is working on a fix for this.

 

And like you said, just delete the class (and associated VF page) as a workaround.

All Answers

awilawil

It turns out that though this controller and the related page are supplied as part of enabling Sites, you can still delete them both from your org. This allows you to continue developing in other areas or saving metadata from the IDE.

Ryan-GuestRyan-Guest

The salesforce.com team technology team is working on a fix for this.

 

And like you said, just delete the class (and associated VF page) as a workaround.

This was selected as the best answer
jovajova

This is very inconvenient. How do I delete?

Ryan-GuestRyan-Guest

The fastest way to delete:

 

- Log into salesforce

- Click on your username (top right)

- Click Setup

- Click Develop

- Click Pages

- Delete the My Profile page

 

 

Click Develop

Click Apex Classes

Delete the class

jovajova

I do not have a "Delete" option for Apex Classes.... please advise Ryan-Guest

Ryan-GuestRyan-Guest

You'll need to use the Force.com IDE then.

 

http://wiki.developerforce.com/index.php/Force.com_IDE

 

Make sure you select the options to include Apex Classes and Pages in your package file.

jovajova

Ugh, why would SFDC release something with 0% test coverage? SUCH. A. PAIN.

narsavagepnarsavagep

Thanks... I thought I was going crazy... I was wondering what happened.

Argh!

narsavagepnarsavagep

I deleted... and I'm able to deploy my code once again. *phew*

My only concern now is: when we do decide to create a customer portal, I'll have to remember to upload this from a sandbox?

I think I may reload the objects now from our sandbox, but comment-out the code, just so it doesn't get "lost"... unless this is something that would automatically be recreated at some point?

 

Andy123Andy123

Thanks for this thread!  I had to create a new force project to be able to delete the MyProfile class, but was finally able to deploy again.  You would think Salesforce could do a search against all of their customers who have this situation (i.e. production won't build!) and either notify the sysadmin of the issue or fix it.  It hasa been over two weeks since this was reported.  Accidents happen - no test code is perfect, but how many developer/admin hours have been spent on this issue and what is SF doing about it?

 

 

ddarmondddarmond

This needs to be resolved.

JasonGablerJasonGabler

Over month and a half and this is still happening.  Fortunately I knew how to find the underlying problem and search for this thread.   I fear for those who do not.

 

Is there some sort of bug news feed or mailing list?  It would've saved me an hour or so had I been aware of this before encountering it.

 

Jason Gabler

Ryan-GuestRyan-Guest

Unfortunately there is not a bug list. 

 

Your best bet is to check this board or email support@salesforce.com

Mattias NordinMattias Nordin

At last i found this thread. To bad the premium support people dont know about this yet !

jhittlemanjhittleman

I have tried deleting the class using the Force.com IDE and I receive the following error: A fatal error occurred while performing the refactoring. Remote delete failed with the following message. Delete will be aborted. MyProfilePageController:null package.xml: null

 

Any suggestions?

Andy123Andy123

I had to create a new force.com project before I could delete the class - the existing project I was working on threw some errors - I can't remember what though...  Not sure if that helps or not.

jhittlemanjhittleman

I ended up having to connect the IDE to the Sandbox, delete the class from there, then Deploy to Server to Production. Thanks!

bem1976bem1976

Dear all,

 

is there any news about this bug?

When Salesforce is planning to fix it?

 

BR,
Enrico

Ricardo SoaresRicardo Soares

Ryan, your information was rich and efficient!

The problem solved.

Greg RohmanGreg Rohman

Nearly two months later, and this is STILL not resolved. Incredibly frustrating, and indicative of the lack of attention that the user base receives from support.

 

-Greg

Andy123Andy123

I grabbed a bunch of quality control guys from Salesforce at the Dreamforce event in SF a few weeks ago and showed them this thread.  They said they would look into it (apparently nothing)...

 

I listened to all of these talks about test coverage, 75%, and about all of the behind-the-scenes testing that Salesforce does to ensure that every custom piece of code compiles before doing any upgrades.  How difficult would it be for them to try and compile the code base for users with this class in their instance?

 

I'm not so surprised that this sort of bug/error gets through QC...  Stuff happens.  What is absolutely astonishing is that they haven't recognized that this as a serious issue.  It has just be dropped into the same bucket as any other minor bug.  I think this is the curse of a large support infrastructure with tier 1, 2, 3...  Sometimes rather important things get stuck in the same bucket as some user who doesn't have js enabled in their browser.

 

Salesforce Support - do you realize that this bug, introducted by SF, causes production instances of your product to essentially be rendered inoperable?  Admins are unable to deploy changes, including critical bug fixes, until this is failing test code is resolved. 

 

While reading this forum makes the solution relatveily trivial, how many admin-hours have been spent researching this issue?  Couldn't a qualified QC guy write a script to try and compile this class on every instance and notify all admins of the affected systems of the issue?  Or, even better, just replace the failing test code with functional test code?  Maybe this has happened already, but you really should follow up and close the loop on the users who were most affected by this issue.

 

JoshGuiJoshGui

So I deleted this class a while ago, because that was the recommended way to go..  Now, however, I am trying to create a new Site, and I get this error message and can't create the new site.

 

 

Error:

Unknown property 'MyProfilePageController.isEdit'

 

I just tried to deploy the class from the sandbox and it won't deploy because it fails its own tester..

 

Any update on this bug?  

Patrick DixonPatrick Dixon

I'm a complete newbie and seem to have run into this trying to get a first free force.com site up.

 

http://boards.developerforce.com/t5/New-to-Cloud-Development/Deployment-failure/m-p/236207

 

Unfortunately I don't understand how to resolve it and move to first base  -I don't want to install the IDE and start all over again since I'm already drowning here.

 

HELP please!

 

 

JoshGuiJoshGui

Yes, this is a major problem for us still too.  I contacted our premier support and they put the MyProfilePageController.cls back in our production so that I could create a new Site.  Then I had to do a fresh deployment from our sandbox 10 minutes later, which then failed, so I had to go back to my ide and comment out the code in that class to deploy.

 

So, as we are heavy users of both Sites and sandbox development, now we have to:

 

1) re-deploy MyProfilePageController.cls everytime we want to create a Site

 

and / or

 

2) Comment out code and re-deploy MyProfilePageController.cls every time we want to deploy new custom classes/triggers/visualforce.

 

It's really awesome.

James S. CloudAnswers.comJames S. CloudAnswers.com

I work in a lot of different orgs that have this problem, so I usually use this version (slight modification) that at least doesn't fail tests:

 

 

/**
 * An apex class that keeps updates of a portal user in sync with its corresponding contact.
   Guest users are never able to access this page.
 */
public class MyProfilePageController {

    private User user;
    private boolean isEdit = false;
    
    public User getUser() {
        return user;
    }

    public MyProfilePageController() {
        user = [SELECT id, email, username, usertype, communitynickname, timezonesidkey, languagelocalekey, firstname, lastname, phone, title,
                street, city, country, postalcode, state, localesidkey, mobilephone, extension, fax, contact.email
                FROM User
                WHERE id = :UserInfo.getUserId()];
        // guest users should never be able to access this page
        if (user.usertype == 'GUEST') {
            throw new NoAccessException();
        }
    }
    
    public Boolean getIsEdit() {
        return isEdit;
    }
    
    public void edit() {
        isEdit=true;
    }    
    
    public void save() {
        if (user.contact != null) {              
            setContactFields(user.contact);
        }
        
        try {
            update user;
            if (user.contact != null) { 
                update user.contact;
            }
            isEdit=false;
        } catch(DmlException e) {
            ApexPages.addMessages(e);
        }
    }
    
    public PageReference changePassword() {
        return Page.ChangePassword;
    }
    
    public void cancel() {
        isEdit=false;
        user = [SELECT id, email, username, communitynickname, timezonesidkey, languagelocalekey, firstname, lastname, phone, title,
                street, city, country, postalcode, state, localesidkey, mobilephone, extension, fax, contact.email
                FROM User
                WHERE id = :UserInfo.getUserId()];
    }
    
    private void setContactFields(Contact c) {
        c.title = user.title;
        c.firstname = user.firstname;
        c.lastname = user.lastname;
        c.email = user.email;
        c.phone = user.phone;
        c.mobilephone = user.mobilephone;
        c.fax = user.fax;
        c.mailingstreet = user.street;
        c.mailingcity = user.city;
        c.mailingstate = user.state;
        c.mailingpostalcode = user.postalcode;
        c.mailingcountry = user.country;
    }

    static testMethod void testSave() {         
        // Modify the test to query for a portal user that exists in your org
        User existingPortalUser = [SELECT id, profileId, userRoleId FROM User WHERE ( UserRoleId <> null AND UserType='CustomerSuccess') or Id = :UserInfo.getUserId() LIMIT 1];
        
        System.assert(existingPortalUser != null, 'This test depends on an existing test portal user to run');
        
        String randFax = Math.rint(Math.random() * 1000) + '5551234';
        
        System.runAs(existingPortalUser) {
            MyProfilePageController controller = new MyProfilePageController();
            System.assertEquals(existingPortalUser.Id, controller.getUser().Id, 'Did not successfully load the current user');
            System.assert(controller.isEdit == false, 'isEdit should default to false');
            controller.edit();
            System.assert(controller.isEdit == true);
            
            controller.cancel();
            System.assert(controller.isEdit == false);
            
            controller.getUser().Fax = randFax;
            controller.save();
            System.assert(controller.isEdit == false);
        }
        
        // verify that the user and contact were updated
        existingPortalUser = [Select id, fax, Contact.Fax from User where id =: existingPortalUser.Id];
        System.assert(existingPortalUser.fax == randFax);
        //System.assert(existingPortalUser.Contact.fax == randFax);
    }

}

 

 

Patrick DixonPatrick Dixon

Sadly I can't even install the IDE on Win XP to resolve this problem:- http://boards.developerforce.com/t5/New-to-Cloud-Development/IDE-won-t-install-on-Win-XP/m-p/236677

 

Heapofcrap software :-(

bryan.gilbertbryan.gilbert

The posted solution does not work for two reasons (although it is a good idea)  First, the instance may be using this class because they are using portal. Second, I and others could not find a way to actually delete the class.  

Here is the solution I got from SF:

 

In MyProfilePageController method testSave() you need to fix the first line and comment out a assertion.  Here is the code I put into our instance (we are not yet using portal but plan on releasing it soon)

 

 

//===============================

// If portal is enabled

// Change

// User existingPortalUser = [SELECT id, profileId, userRoleId FROM User WHERE UserRoleId <> null

// AND UserType='CustomerSuccess' LIMIT 1];

//

//to

// 

// User existingPortalUser = [SELECT id, profileId, userRoleId FROM User WHERE UserRoleId <> null

// AND isportalEnabled=True AND isActive=true LIMIT 1];

//

//===============================

// If portal is not enabled

// Change

// to

 

User existingPortalUser = [SELECT id, profileId, userRoleId FROM User WHERE UserRoleId <> null

AND isActive=true LIMIT 1];

 

//and comment out/delete the assert below.

// System.assert(existingPortalUser.Contact.fax == randFax)     

Patrick DixonPatrick Dixon

LOL, with that I get a :-


System.QueryException: List has no rows for assignment to SObject    MyProfilePageController.cls   /classes    line 88    Force.com run test failure

 

But it's acedemic anyway, because if I don't remove the body of that class, overall test coverage drops to below 75% even though my own code is at 100%.  I guess you need lots of your own 'good' code, to make up for salesforce's 'bad' code!

 

You've gotta love this 'trust the cloud' stuff!

James S. CloudAnswers.comJames S. CloudAnswers.com

I don't condone using this.... ;)

 

public static testMethod void test1(){fakecode();}

public static void fakecode(){

Integer i=0;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;

i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;

i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;

i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;

i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;

i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;

i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;

}

JoshGuiJoshGui

hahahaaa, oh good stuff, good stuff.  Thanks, James.

gwpgwp

After calling support I was told that they could not help. This is SF code, and they cannot help????

Doesn't this have the potential to affect everyone using force.com and the partnerportal?

gwpgwp

Hi there,

 

I fixed this myself by rewriting the test case:

 

 

static testMethod void testSave() {
    	//Hacked by GWP for a minimum pass for this class as the old test crashed and prevented Apex releases (the customer portal was required to be activated to allow the test to work - and we don't use the customer portal - so the old script never passed it's test case, stopping releases in their tracks)
        
 	//An Account
	Account ac = new Account();
	ac.Name = 'Test Entity';
    	insert ac;
		
        //A Contact
        Contact c = new Contact();
        c.FirstName = 'unit';
        c.LastName = 'test';
        c.Email = 'it@gwpforum.org';
        c.AccountId = ac.Id;
        insert c;        
        
        String randFax = Math.rint(Math.random() * 1000) + '5551234';
        MyProfilePageController controller = new MyProfilePageController();
        controller.save();
        controller.edit();
        controller.cancel();
        controller.getUser().Fax = randFax;
        controller.setContactFields(c);
    }

 

Don't get me wrong, SF is cool and interesting tech but this is just SLOPPY coding on behalf of the SF team, contravening their own standards (not that my test case is worth much, but at least it gets a pass)

 

Chirag MehtaChirag Mehta

Thank you this helped and even saved time to recode same :)