Your failure is in the constructor of GenerateJobOfferController.
A query (on line 6) is not finding any records and you are assigning it directly to a single sObject. This causes salesforce to throw an exception.
Without seeing the code for that class its hard to give more specific details. Are you using a page parameter in a query?
acc = [SELECT Id, ... FROM Account WHERE Id = :ApexPages.currentPage().getParameters().get('id')];
If so, you need to set it up in your test:
static testMethod void myUnitTest() {
// TO DO: implement unit test
LoadData();
//set up query param
Test.setCurrentPageReference(new PageReference('Page.myPage'));
System.currentPageReference().getParameters().put('id', objAccount.Id);
ApexPages.StandardController stdController = new ApexPages.StandardController(objApplication);
GenerateJobOfferController objGenerateJobOfferController = new GenerateJobOfferController(stdController);
}
Your issue with both your trigger and your test class are because you've hardcoded a userId into your code. This is a very poor practice. You're much safer to select a profile to use for the user who will have the correct permissions to perform the operation.
Further, the user in your sandbox will have a different Id in production than in your sandbox. Regardless, it's not clear why you'd want to limit your trigger to a single user. If you in fact did need this requirement, for security reasons, you'd want to do one of the following to retrieve the userId during runtime:
- store it in a custom setting
- store it in custom metadata
Your test should also use a "RunAs" user. Here's more on the RunAs user and best practices for using one in a unit test:
private class TestRunAs {
public static testMethod void testRunAs() {
// Setup test data
// This code runs as the system user
Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
User u = new User(Alias = 'standt', Email='standarduser@testorg.com',
EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US',
LocaleSidKey='en_US', ProfileId = p.Id,
TimeZoneSidKey='America/Los_Angeles', UserName='standarduser@testorg.com');
// Role = 'some Role'; this would be specific to your org if it uses roles
System.runAs(u) {
// The following code runs as user 'u'
System.debug('Current User: ' + UserInfo.getUserName());
System.debug('Current Profile: ' + UserInfo.getProfileId()); }
}
}
You can nest more than one runAs method. For example:
@isTest
private class TestRunAs2 {
public static testMethod void test2() {
Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
User u2 = new User(Alias = 'newUser', Email='newuser@testorg.com',
EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US',
LocaleSidKey='en_US', ProfileId = p.Id,
TimeZoneSidKey='America/Los_Angeles', UserName='newuser@testorg.com');
Role='Support'; // again, specific to your org.
System.runAs(u2) {
// The following code runs as user u2.
System.debug('Current User: ' + UserInfo.getUserName());
System.debug('Current Profile: ' + UserInfo.getProfileId());
// The following code runs as user u3.
User u3 = [SELECT Id FROM User WHERE UserName='newuser@testorg.com'];
System.runAs(u3) {
System.debug('Current User: ' + UserInfo.getUserName());
System.debug('Current Profile: ' + UserInfo.getProfileId());
}
// Any additional code here would run as user u2.
}
}
}
Best Practices for Using runAs
The following items use the permissions granted by the user specified with runAs running as a specific user:
Dynamic Apex
Methods using with sharing or without sharing
Shared records
The original permissions are reset after runAs completes.
The runAs method ignores user license limits. You can create new users with runAs even if your organization has no additional user licenses.
Best Answer
Precisely. The "List has no rows for assignment" means that you tried to assign the result of a query that returned no records to a variable.
If you get a "List has more than 1 row for assignment to SObject" error it would mean the opposite: you got more than one record in your query, and you are trying to assign it to a single instance in your code. In this case you need to either refine your query to get just one record or change your variable type to a list.
Edit:
So, after reading your code, some things come to my mind:
seeAlldata=true
in your class. This means that when the test is run, it will be able to read the data in your organization. No big deal, actually, but you might not need this, see below.seeAllData=true
useless.TestBillingSchedule1
andTestBillingSchedule2
are methods that will be using the test data created previously. If they are failing then you need to fix whatever is causing the error (in this case, the Asset is missing from the test data).AssetTriggerHandlerTest
class is also failing, you might want to check it before, since it is testing a trigger. The trigger behaviour will likely affect other tests, like the first one you posted.