Apex Test Class for Invocablemethods - salesforce

I'm brand new to writing apex and especially test classes in apex. I can’t seem to find out how to properly call my class method in my test class it seems like. My test class is definitely not finished but I'm just starting with one of my delete methods.
I seem to be getting stuck on line 17 on my test class “CreateQuoteProducts_OtherOpp.DeleteQuoteProductsOTFOther(testQPOTF.id);” I’m getting an error that states:
Method does not exist or incorrect signature: void DeleteQuoteProductsOTFOther(Id) from the type CreateQuoteProducts_OtherOpp
I think I just need to pass in the OrderId but I’m not too sure what I’m doing wrong.
This is my apex class
public class CreateQuoteProducts_OtherOpp{
#invocableMethod
public static void DeleteQuoteProductsMRFOther(List<Id> OrderId){
List<Quote_Product_MRF__c> QuoteProductsMRFOther = [SELECT id from Quote_Product_MRF__c WHERE Order__c in : OrderId];
if(!QuoteProductsMRFOther.isEmpty()){
delete QuoteProductsMRFOther;
}
}
public static void DeleteQuoteProductsOTFOther(List<Id> OrderId){
List<Quote_Product__c> QuoteProductsOTFOther = [SELECT id from Quote_Product__c WHERE Order__c in : OrderId];
if(!QuoteProductsOTFOther.isEmpty()){
delete QuoteProductsOTFOther;
}
}
/* ---START--- Create Quote Products MRF ---START--- */
public void CreateQuoteProductsMRFOther(List<Id> OrderId){
List<AggregateResult> nrqpmrfOPOther = [
SELECT
count(Id) ct,
Order__c ord,
sum(Total_Monthly_Recurring_Fees__c) stmr,
sum(Monthly_Recurring_Fees__c) mr,
sum(Discount_MRF__c) dmr
FROM Order_Location_Package__c
WHERE Order__c in : OrderId AND Package__r.Monthly_Recurring_Price__c != null AND Package_Status__c = 'New'
GROUP BY Package__c, Order__c];
List<Quote_Product_MRF__c> nrqpmrfOther = New List<Quote_Product_MRF__c>();
for(AggregateResult ar : nrqpmrfOPOther){
Quote_Product_MRF__c QuoteProductMRF = New Quote_Product_MRF__c();
QuoteProductMRF.Quantity__c = (Decimal)ar.get('ct');
QuoteProductMRF.Order__c = (String)ar.get('ord');
QuoteProductMRF.Total_Monthly_Recurring_Fees__c = (Decimal)ar.get('stmr');
QuoteProductMRF.Monthly_Recurring_Fees__c = (Decimal)ar.get('mr');
QuoteProductMRF.Discount_MRF__c = (Decimal)ar.get('dmr');
QuoteProductMRF.Product_Type__c = 'Package';
nrqpmrfOther.add(QuoteProductMRF);
}
Insert nrqpmrfOther;
}
/* ---END--- Create Quote Products MRF ---END--- */
/* ---START--- Create Quote Products OTF ---START--- */
public void CreateQuoteProductsOTFOther(List<Id> OrderId){
List<AggregateResult> nrqpotfOPOther = [
SELECT
count(Id) ct,
Order__c ord,
sum(Total_One_Time_Fees__c) stmr,
sum(One_Time_Fees__c) mr,
sum(Discount_OTF__c) dmr
FROM Order_Location_Package__c
WHERE Order__c in : OrderId AND Package__r.One_Time_Price__c != null AND Package_Status__c = 'New'
GROUP BY Package__c, Order__c];
List<Quote_Product__c> nrqpotfOther = New List<Quote_Product__c>();
for(AggregateResult ar : nrqpotfOPOther){
Quote_Product__c QuoteProductOTF = New Quote_Product__c();
QuoteProductOTF.Quantity__c = (Decimal)ar.get('ct');
QuoteProductOTF.Order__c = (String)ar.get('ord');
QuoteProductOTF.Total_One_Time_Fees__c = (Decimal)ar.get('stmr');
QuoteProductOTF.One_Time_Fees__c = (Decimal)ar.get('mr');
QuoteProductOTF.Discount_OTF__c = (Decimal)ar.get('dmr');
QuoteProductOTF.Product_Type__c = 'Package';
nrqpotfOther.add(QuoteProductOTF);
}
Insert nrqpotfOther;
}
/* ---END--- Create Quote Products ORD ---END--- */
}
And this is my test class I’m writing
#isTest
private class CreateQuoteProducts_OtherOppTest {
private static testMethod void doTest() {
Order_Sheet__c testOrder = new Order_Sheet__c ();
testOrder.Opportunity__c = 'Opportunity';
insert testOrder;
Test.startTest();
/* --- Create Quote Product OTF--- */
Quote_Product__c testQPOTF = new Quote_Product__c ();
testQPOTF.Order__c = testOrder.id;
insert testQPOTF;
/* --- Run Delete Method--- */
CreateQuoteProducts_OtherOpp.DeleteQuoteProductsOTFOther(testQPOTF.id);
/* --- Query for QP OTF--- */
list<Quote_Product__c>queriedQPOTF = [Select Id FROM Quote_Product__c WHERE Order__c = :testOrder.id];
/* --- Checks for 0 records --- */
system.assertEquals(0, queriedQPOTF.size());
Test.stopTest();

public static void DeleteQuoteProductsOTFOther(List<Id> OrderId) accepts list of Ids. You try to pass a single Id: CreateQuoteProducts_OtherOpp.DeleteQuoteProductsOTFOther(testQPOTF.id);
It's like "array of integers" and "one integer" are not compatible types. If you will not need that list for anything else you can create it in-flight and it'll be then discarded when that line of code finishes:
CreateQuoteProducts_OtherOpp.DeleteQuoteProductsOTFOther(new List<Id>{testQPOTF.id});
This should compile fine

Related

Guys I don't understand how to write tests

I have a class in which I get the number of ids per year with a soql query on a custom object:
public static Integer numberRecords(Integer year) {
List<AggregateResult> numbersOfRecords = [
SELECT Keeper__c
FROM Month_Expense_Application__c
WHERE calendar_year(MonthDate__c) =: year
];
Set<Id> keepers = new Set<Id>();
for (AggregateResult result : numbersOfRecords) {
keepers.add((Id)result.get('Keeper__c'));
}
Integer value = keepers.size();
return value;
}
I'm trying to write a test for this method by creating an object and filling in the fields it needs, then I try to get the id with a soql request and compare:
#isTest
public class ExpenseAdminControllerTests {
#isTest
public static void numberRecordsTests() {
Month_Expense_Application__c monthExpenseTest = new Month_Expense_Application__c(
Balance__c = 12.3,
Income__c = 11,
Keeper__c = '0034x00001K7kGCAAZ',
MonthDate__c = date.newInstance(2022, 11, 21)
);
Integer year = 2022;
List<Month_Expense_Application__c> numbersOfRecords = [
SELECT Keeper__c
FROM Month_Expense_Application__c
WHERE calendar_year(MonthDate__c) =: year AND Id =: monthExpenseTest.Id
];
Set<Id> keepers = new Set<Id>();
keepers.add(numbersOfRecords[0].Keeper__c);
Integer value = keepers.size();
System.assertEquals(1, value);
}
}
But i cant tell me what am i doing wrong
I guess you just forgot to insert "monthExpenseTest" in actual database, by means that you have just created a object by using below lines as you mentioned
Month_Expense_Application__c monthExpenseTest = new Month_Expense_Application__c(
Balance__c = 12.3,
Income__c = 11,
Keeper__c = '0034x00001K7kGCAAZ',
MonthDate__c = date.newInstance(2022, 11, 21)
);
by writing above lines you just created object which is present in memory only. it is not stored in database, so that it is not fetched when you try to fetch it via SOQL Query.
Now you may want to add one more line after above code.which is given as below
insert monthExpenseTest ;
so after inserting your object is stored in database. now you can fetch it via SOQL query.
So your test class will be looks like below
#isTest
public class ExpenseAdminControllerTests {
#isTest
public static void numberRecordsTests() {
Month_Expense_Application__c monthExpenseTest = new Month_Expense_Application__c(
Balance__c = 12.3,
Income__c = 11,
Keeper__c = '0034x00001K7kGCAAZ',
MonthDate__c = date.newInstance(2022, 11, 21)
);
insert monthExpenseTest;
Integer year = 2022;
Integer keepers = ExpenseAdminController.numberRecords(year);
System.assertEquals(1, keepers);
}
}
So when you are testing ExpenseAdminController then you just need to call that method because you want to test it. in test class which is mentioned in question it not testing numberRecords() method instead of you are rewriting logic.

How to get query covered in apex test class for salesforce

I'm having a tough time trying to get all code covered in my test class for an apex class.
Apex class:
public with sharing class myclass {
**public List<CustomObject1> listvar {get;set;}**
public myclass(ApexPages.StandardController sc){
CustomObject2 var = [SELECT Id, Field1__c FROM CustomObject2 WHERE Id = :ApexPages.currentPage().getParameters().get('id')];
**listvar = [SELECT Id,Name,Field1__c,Field2__c,Field3__c,Field4__c,Field5__c,CreatedDate,CreatedById FROM CustomObject1 WHERE Field2__c = :var.Field1__c ORDER BY CreatedDate DESC];**
}
}
Test Class:
#isTest
public class myclass_Test {
static testmethod void dosomething(){
Account a = new Account();
a.Name = 'Test acct';
insert a;
CustomObject4__c v = new CustomObject4__c();
v.Field1__c = '123 ABC';
v.Name = 'test name';
v.Field2__c = True;
v.Account__c = a.Id;
insert v;
... more record creates including ones for the object being queried...
PageReference pageref = Page.myVFpage;
Test.setCurrentPageReference(pageref);
ApexPages.StandardController sc = new ApexPages.StandardController(v);
myclass myPageCon = new myclass(sc);
}
}
I've tried creating a new list for the underneath the last line in the test class and populating the list, but I cannot get 100% code coverage. I marked the lines that I'm not getting any coverage from the test class with. Any suggestions?
You should put some asserts into your test Class. Something like
System.assertEquals(5, yourListsize)
I figured out that the listvar list for CustomObject1 wasn't getting populated because an Id wasn't being passed to var for CustomObject2. In the test class I had to put the record Id using ApexPages.currentPage().getParameters().put('Id', something.id);
with the Id for the record created in the test class for that object. Thanks anyways guys :-)

How to get the code coverage required to deploy Apex Class

Please Help!!!
I have this Apex controller class that I'm trying to deploy from Salesforce Sandbox to Production but I'm not getting the code coverage required!!
the class is consuming 3 objects, one is stranded and 2 are custom and constructing a hierarchy tree view for those three objects.
//Apex Class
public class TeeView {
/* Wrapper class to contain the nodes and their children */
public class cNodes
{
Public StandardObject gparent {get;set;}
public List<CustomObject1__c> parent {get; set;}
Public List<CustomObject2__c> child {get;set;}
public cNodes(StandardObject gp, List<CustomObject1__c> p, List<CustomObject2__c> c)
{
parent = p;
gparent = gp;
child = c;
}
}
/* end of Wrapper class */
Public List<cNodes> hierarchy;
Public List<cNodes> getmainnodes()
{
hierarchy = new List<cNodes>();
List<StandardObject> tempparent = [Select Id,Name , End_Date__c, Owner.Name Account.Name from Contract ];
for (Integer i =0; i< tempparent.size() ; i++)
{
List<CustomObject1__c> tempchildren = [Select Id,Name, Owner.Name , (select Id,Name, Owner.Name from CustomObject2__r) from CustomObject1__c where Related_Field__c = :tempparent[i].Id];
List<CustomObject2__c> tempchild = [Select Id,Name Owner.Name from CustomObject2__c where Related_Field__c= :tempparent[i].Id];
hierarchy.add(new cNodes(tempparent[i],tempchildren, tempchild));
}
return hierarchy;
}
}
//Test Class
#isTest
public class treeviewTest
{
static testMethod void test1()
{
test.startTest();
Account acc = new Account(Name = 'Unit test account');
insert acc;
StandardObject c = new StandardObject(
Name = 'test',
AccountId = acc.Id,
Status = 'Draft',
StartDate = System.today());
try
{
insert c;
}
catch (Exception ex)
{
ApexPages.addMessages(ex);
}
List<StandardObject> standard = [select Id, Name from StandardObject where Name = 'test'];
system.assertequals(standard.size(), 1);
CustomObject1__c s = new CustomObject1__c(
Related_StandardObjectField__c = c.Id,
Name = 'test'
);
try
{
insert s;
}
catch (Exception ex)
{
ApexPages.addMessages(ex);
}
List<CustomObject1__c> cus1 = [select Id, Name from CustomObject1__c where Name = 'test'];
system.assertequals(cus1.size(), 1);
insert new CustomObject2__c(Related_StandardObjectField__c = c.Id, Description__c = 'test');
List<CustomObject2__c> cus2 = [select Id, Name from CustomObject2__c where Description__c = 'test'];
system.assertequals(cus2.size(), 1);
insert new CustomObject2__c(Related_CustomObject1Field__c = s.Id, Description__c = 'test');
List<Mods__c> cus3 = [select Id, Name from Mods__c where Description__c = 'test'];
system.assertequals(cus3.size(), 1);
treeView view = new treeView();
view.getmainnodes();
test.stopTest();
}
}
Oh man, where do we even start... Looks like you copy-pasted some code at random trying to get the test to work? Your code works on Contract, CustomObject1__c, CustomObject2__c. Your unit test inserts Contract, Subaward__c, Mods__c. Was this some attempt at anonymizing your code? And what's this List<StandardObject> thing, it shouldn't even compile.
I think you need help of a developer with more experience, you've cobbled something together but it doesn't follow the Salesforce best practices for code...
About the main class
Smart use of subqueries will mean
you waste less SOQL (it's bad idea to blindly select all records without any filters but whatever),
don't run into errors related to "too many SOQL statements" (the limit is 100 so since you query in a loop - your code will crash and burn the moment you have around 50 Contracts)
lead to compact code occupying less lines (easier to maintain & cover with tests).
I'd go with something like that, query Contract & first related list in one go and then the parents + children in another query. Using a Map to link them for displaying.
List<Contract> levelOneAndTwo = [SELECT Id, Name, End_Date__c, Owner.Name, Account.Name,
(SELECT Id,Name, Owner.Name FROM Subawards__r)
FROM Contract];
Map<Id, SubAward__c> levelTwoAndThree = new Map<Id, Subaward__c>([SELECT Id,
(SELECT Id,Name Owner.Name FROM Mods__r)
FROM Subaward__c WHERE Contract__c = :levelOneAndTwo];
);
This wastes only 2 queries but fetches all contracts and their related data. Then you can loop over results building your wrapper object or just feed it directly to Visualforce for displaying.
About the unit test
You don't get the coverage because you're spread too thin. One unit test methods inserts only Contracts (so your main query will hit something, give you some coverage). Then another method (in completely different context) inserts some child objects - but they don't matter. In that other method there are 0 contracts so it won't even enter your main loop. Combine it into one?
Account acc = new Account(Name = 'Unit test account');
insert acc;
Contract c = new Contract(
Name = 'test contract',
AccountId = acc.Id,
Status = 'Draft',
StartDate = System.today()
);
insert c;
Subaward__c s = new Subaward(
Contract__c = c.Id,
Name = 'test'
);
insert s;
insert new Mod__c(Subaward__c = c.Id, Description__c = 'test');
Now you have nice tree hierarchy set up, from Account all the way down. Queries in the test should hit some data.
I was finally able to get %100 code coverage for the above class by adding these lines to the test class:
treeView view = new treeView();
view.getmainnodes();
system.assert(view.hierarchy.size() > 0);

FIELD_CUSTOM_VALIDATION_EXCEPTION

I am writing a test class for a trigger. But i am not able to run it properly it only contain 68%.
The error is
System.DmlException: Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, This part is not forecastable.
#isTest
private class TestTriggers
{
static testMethod void testService()
{
//Insert part
list<Opportunity> Opportunity = new list<Opportunity>();
Opportunity = [Select id from Opportunity];
list<Product2> Product = new list<Product2>();
Product = [Select id from Product2];
Part__c p = new Part__c(Stage__c = 'idea',Product__c=Product[0].id,Opportunity__c=Opportunity[0].id);
insert p;
//Update part
list<part__c> partlist = new list<part__c>();
partlist = [Select Stage__c from part__c where Stage__c = 'idea'];
partlist[0].Stage__c = 'update';
update partlist;/* */
}
}
thanks
Anuraj
There is a validation rule on the Part object. To view the validation rule(s), go to Setup > Create > Objects > Part > Validation Rules.
You'll need to modify your code to create a Part__c record that complies with the validation rules.

joining two different table

i have couple of tables that i am joining
organization table:
id, name
registration table:
id, name
after i execute this is how it looks
org_id org_name reg_name reg_id
--------------------------------------------------------
329 abc regname1 311
329 abc regname2 298
what i want to do is to display the data ONE row like this:
org_id org_name reg_name reg_id
------------------------------------------------------------------------
329 abc regname1;regname2 311;298
note: my reg_name is dynamic, it might be one or ten.
I'd say give this post a try: comma separated list in SQL-server.
What you're looking for is a SQLCLR custom aggregator. You would then use your hand crafted custom aggregator in much the same way you'd use the SUM aggregator.
A rough-cut custom aggregator that will accumulate strings, sort them and then join with a semi-colon would looke like this:
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize=-1)]
public struct JoinString : IBinarySerialize
{
List<String> strings;
public void Init()
{
strings = new List<String>();
}
public void Accumulate(SqlString input)
{
strings.Add(input.Value);
}
public void Merge(JoinString Group)
{
strings.AddRange(Group.strings.ToArray());
}
public SqlString Terminate()
{
strings.Sort();
return new SqlString(String.Join(";", strings.ToArray()));
}
public void Read(System.IO.BinaryReader r)
{
int items = r.ReadInt32();
strings = new List<String>(items);
for (var i = 0; i < items; i++)
strings.Add(r.ReadString());
}
public void Write(System.IO.BinaryWriter w)
{
w.Write(strings.Count);
foreach (var s in strings)
w.Write(s);
}
}
In Oracle, you can use the list_aggr function also.
For example:
SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
FROM emp
GROUP BY deptno;
Your query should like something:
SELECT a.org_id,a.org_nam, LISTAGG(reg_name, ';') WITHIN GROUP (ORDER BY a.org_id) AS reg_name, LISTAGG(reg_id, ';') WITHIN GROUP (ORDER BY a.org_id) AS reg_id
FROM organization a , registration b
where b.org_id = a.org_id
GROUP BY a.org_id,a.org_nam;

Resources