write a test class for apex class - apex

I am new to apex, I'm interested in writing a test class for the following controller, but not sure where to begin. Here is my apex class code.
public class tree {
public Account acct{get;set;}
//private final Account acct;
public ApexPages.StandardController stdController {get;set;}
public tree(ApexPages.StandardController stdController) {
stdController.addFields(new String[]{'Id','Tete_de_groupe__c'});
this.acct = (Account)stdController.getRecord();
// this.stdController = stdController;
}
public List<Account> listOfAccount(){
List<Account> acctList;
if (acct.Tete_de_groupe__c == null){
acctList = [SELECT Name,Parent.Name,id,Code_NAF__c ,Industry ,RecordType.Name,Adresse_Agence__c, Tete_de_groupe__c,Statut__c
FROM Account
where id = :this.acct.id or Tete_de_groupe__c = :this.acct.id ];}
else {
acctList = [Select Name,Parent.Name,id,Tete_de_groupe__c,Statut__c
from Account
where id = :this.acct.Tete_de_groupe__c or Tete_de_groupe__c = :this.acct.Tete_de_groupe__c];}
return acctList;
}
Public String getaccountdata(){
String datastr1 = '';
String datastr2 = '';
String datastr = '';
List<Account> lstOfAcc =listOfAccount();
for (integer i=0;i<lstOfAcc.size();i++){
if (lstOfAcc[i].Parent.Name == null){
datastr1 = datastr1 + '{"name": "';
datastr1+= lstOfAcc[i].Name;
datastr1+= '","parent": ';
datastr1+= lstOfAcc[i].Parent.Name;
datastr1+= ',"accountid": "';
datastr1+= lstOfAcc[i].id;
datastr1+= '","Statut__c": "';
datastr1+= lstOfAcc[i].Statut__c;
datastr1+='" }';
}
else{
datastr2 = datastr2 + '{"name": "';
datastr2+= lstOfAcc[i].Name;
datastr2+= '","parent": "';
datastr2+= lstOfAcc[i].Parent.Name;
datastr2+= '","accountid": "';
datastr2+= lstOfAcc[i].id;
datastr2+= '","Statut__c": "';
datastr2+= lstOfAcc[i].Statut__c;
datastr2+='" },';
}
}
if(datastr2 == ''){datastr = '[' + datastr1 + ']';}
else {
datastr2 = datastr2.substring(0,datastr2.length()-1);
datastr = '[' + datastr1 +','+ datastr2 + ']'; }
return datastr;
}
}
I want to create test class. Guys need help if some one can tell me about test class of this apex class.

AParise pointed out the consideration. What you need to do in your test class, step by step:
Insert some account objects into the database (the test runs doesn't see any data by default, and that's OK)
Keep the ID from the first account and use it for Tete_de_groupe__c for the others.
Call the function, roughly like this:
Account mainAccount = populateTestAccounts(); // Helper function
Tree t = new Tree();
t.setAcct(mainAccount);
String result = t.getaccountdata();
assert(....);
That should do the trick!

For unit tests regarding classes like the one you posted, the easiest way is to think about expected results given a code path. For each test method, ask yourself: "Given this set of data, when I invoke this method, I expect this to occur".
Let's walk through your "getaccountdata" method.
"Given this set of data..." - What data does this method require for proper execution? Without diving too deep into your logic, this probably means inserting some Account sObjects.
"When I invoke this method..." - the "getaccountdata" method is being invoked.
"I expect this to occur..." - This is where your assertions come into play. You created the Account sObjects with specific values, so verify that these values propagated into your method return value.

Related

Get set not covering in Test Class - Apex

Getter , setter in test class not getting covered
Here is the code ?
Method :
public static List<SelectOption> UserList
{
get
{
/*string role='';
if(issueTeam == 'Contracts')
role = 'Contract Owner';
else if(issueTeam == 'Buyer')
role = 'Buyer';
else
role = 'Master Data Allocator';*/
UserTemp = [Select u.LastName, u.Id, u.FirstName,u.Name, u.Email From User u ORDER BY u.Name];
UserList = new List<SelectOption>();
UserList.add(new SelectOption('--Select--','--Select--'));
for(User temp : UserTemp)
{
UserList.add(new SelectOption(temp.Id, temp.Name));
}
return UserList;
}
set;
}
In Test Class
I am calling like this :
List<SelectOption> temp1 = TaskReportingMasterDataIssueController.UserList;
Please do respond !!!!!
Well, as I read your code, I understand you should make multiple test cases and in each one of them provide the corresponding values to issueTeam and query records so that all of the code is executed.
In the test line you have provided you are not including any context so I assume you're missing it in your tests.

Custom procedure fails to collect properties of a class parameter; why?

OK, first of all, I'm a rookie with Caché, so the code will probably be poor, but...
I need to be able to query the Caché database in Java in order to rebuild source files out of the Studio.
I can dump methods etc without trouble, however there is one thing which escapes me... For some reason, I cannot dump the properties of parameter EXTENTQUERYSPEC from class Samples.Person (namespace: SAMPLES).
The class reads like this in Studio:
Class Sample.Person Extends (%Persistent, %Populate, %XML.Adaptor)
{
Parameter EXTENTQUERYSPEC = "Name,SSN,Home.City,Home.State";
// etc etc
}
Here is the code of the procedure:
CREATE PROCEDURE CacheQc.getParamDesc(
IN className VARCHAR(50),
IN methodName VARCHAR(50),
OUT description VARCHAR(8192),
OUT type VARCHAR(50),
OUT defaultValue VARCHAR(1024)
) RETURNS NUMBER LANGUAGE COS {
set ref = className _ "||" _ methodName
set row = ##class(%Dictionary.ParameterDefinition).%OpenId(ref)
if (row = "") {
quit 1
}
set description = row.Description
set type = row.Type
set defaultValue = row.Default
quit 0
}
And the Java code:
private void getParamDetail(final String className, final String paramName)
throws SQLException
{
final String call
= "{ ? = call CacheQc.getParamDesc(?, ?, ?, ?, ?) }";
try (
final CallableStatement statement = connection.prepareCall(call);
) {
statement.registerOutParameter(1, Types.INTEGER);
statement.setString(2, className);
statement.setString(3, paramName);
statement.registerOutParameter(4, Types.VARCHAR);
statement.registerOutParameter(5, Types.VARCHAR);
statement.registerOutParameter(6, Types.VARCHAR);
statement.executeUpdate();
final int ret = statement.getInt(1);
// HERE
if (ret != 0)
throw new SQLException("failed to read parameter");
System.out.println(" description: " + statement.getString(4));
System.out.println(" type : " + statement.getString(5));
System.out.println(" default : " + statement.getString(6));
}
}
Now, for the aforementioned class/parameter pair the condition marked // HERE is always triggered and therefore the exception thrown... If I comment the whole line then I see that all three of OUT parameters are null, even defaultValue!
I'd have expected the latter to have the value mentioned in Studio...
So, why does this happen? Is my procedure broken somewhat?
In first you should check that you send right value for className and paramName, full name and in right case and. Why you choose storage procedures, when you can use select? And you can call your procedure in System Management Portal to see about probable errors.
select description, type,_Default "Default" from %Dictionary.ParameterDefinition where id='Sample.Person||EXTENTQUERYSPEC'
Your example, works well for me.
package javaapplication3;
import com.intersys.jdbc.CacheDataSource;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
public class JavaApplication3 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws SQLException {
CacheDataSource ds = new CacheDataSource();
ds.setURL("jdbc:Cache://127.0.0.1:56775/Samples");
ds.setUser("_system");
ds.setPassword("SYS");
Connection dbconnection = ds.getConnection();
String call = "{ ? = call CacheQc.getParamDesc(?, ?, ?, ?, ?)}";
CallableStatement statement = dbconnection.prepareCall(call);
statement.registerOutParameter(1, Types.INTEGER);
statement.setString(2, "Sample.Person");
statement.setString(3, "EXTENTQUERYSPEC");
statement.registerOutParameter(4, Types.VARCHAR);
statement.registerOutParameter(5, Types.VARCHAR);
statement.registerOutParameter(6, Types.VARCHAR);
statement.executeUpdate();
int ret = statement.getInt(1);
System.out.println("ret = " + ret);
System.out.println(" description: " + statement.getString(4));
System.out.println(" type : " + statement.getString(5));
System.out.println(" default : " + statement.getString(6));
}
}
end result
ret = 0
description: null
type : null
default : Name,SSN,Home.City,Home.State
UPD:
try to change code of your procedure and add some debug like here
Class CacheQc.procgetParamDesc Extends %Library.RegisteredObject [ ClassType = "", DdlAllowed, Owner = {UnknownUser}, Not ProcedureBlock ]
{
ClassMethod getParamDesc(className As %Library.String(MAXLEN=50), methodName As %Library.String(MAXLEN=50), Output description As %Library.String(MAXLEN=8192), Output type As %Library.String(MAXLEN=50), Output defaultValue As %Library.String(MAXLEN=1024)) As %Library.Numeric(SCALE=0) [ SqlName = getParamDesc, SqlProc ]
{
set ref = className _ "||" _ methodName
set row = ##class(%Dictionary.ParameterDefinition).%OpenId(ref)
set ^debug($i(^debug))=$lb(ref,row,$system.Status.GetErrorText($g(%objlasterror)))
if (row = "") {
quit 1
}
set description = row.Description
set type = row.Type
set defaultValue = row.Default
quit 0
}
}
and after some test from java, check zw ^debug
SAMPLES>zw ^debug
^debug=4
^debug(3)=$lb("Sample.Person||EXTENTQUERYSPEC","31#%Dictionary.ParameterDefinition","ERROR #00: (no error description)")
Well, uh, I found the problem... Talk about stupid.
It happens that I had the Samples.Person class open in Studio and had made a "modification" to it; and deleted it just afterwards. Therefore the file was "as new"...
But the procedure doesn't seem to agree with this statement.
I closed the Studio where that file was, selected not to modify the "changes", reran the procedure again, and it worked...
Strangely enough, the SQL query worked even with my "fake modification". I guess it's a matter of some cache problem...

more than one field cannot be used to specify a receiver

I'm trying to get delayed chained payments working through PayPal's Adaptive Payments API in C#.
The error I'm getting doesn't make any sense and I can't find anything on the .NET to resolve the issue.
The error message is:
Invalid request: More than one field cannot be used to specify a receiver
Here's the request I'm sending:
requestEnvelope.errorLanguage=en_US
&actionType=PAY_PRIMARY
&cancelUrl=http%3a%2f%2flocalhost%2fccc%2fProgramsandServices%2fCommunityFundingInitiative%2fOopsSome thingWentWrong!.aspx ¤cyCode=USD
&feesPayer=EACHRECEIVER
&ipnNotificationUrl=http%3a%2f%2flocalhost%2fccc%2fdesktopmodules%2fUCU_ProjectManagement%2fPayPalIPN.aspx
&receiverList.receiver(0).amount=10.00
&receiverList.receiver(0).email=A_VALID_SANDBOX_EMAIL_ACCOUNT_ADDRESS_FOR_BUSINESS_OWNER
&receiverList.receiver(0).phone.countryCode=001
&receiverList.receiver(0).phone.phoneNumber=VALID_PHONE_NUMBER
&receiverList.receiver(0).primary=true
&receiverList.receiver(0).invoiceId=51%7c1%7c6%2f16%2f2013+4%3a35%3a56+PM
&receiverList.receiver(0).paymentType=GOODS
&receiverList.receiver(1).amount=9.5000
&receiverList.receiver(1).email=A_VALID_SANDBOX_EMAIL_ACCOUNT_ADDRESS
&receiverList.receiver(1).phone.countryCode=001
&receiverList.receiver(1).phone.phoneNumber=VALID_PHONE_NUMBER
&receiverList.receiver(1).primary=false
&receiverList.receiver(1).invoiceId=51%7c1%7c6%2f16%2f2013+4%3a35%3a56+PM
&receiverList.receiver(1).paymentType=GOODS
&reverseAllParallelPaymentsOnError=false
&senderEmail=A_VALID_SANDBOX_PERSONAL_EMAIL_ACCOUNT
&returnUrl=http%3a%2f%2flocalhost%2fccc%2fProgramsandServices%2fCommunityFundingInitiative%2fThankYouforYourDonation.aspx
&trackingId=51%7c0%7c6%2f16%2f2013+4%3a35%3a56+PM&
I specified two receivers, one is Primary other is not.
What am I missing?
I've tried both PAY and PAY_PRIMARY as the action types. Same results for either one.
If I only use ONE reciever, it works.
Here's the code:
WebClient webClient = new WebClient();
// Receivers
ReceiverList receiverList = new ReceiverList();
// Primary Receiver
Receiver receiver = new Receiver();
receiver.accountId = null;
receiver.amount = Convert.ToDecimal(txtPledgeAmount.Text.Trim());
receiver.invoiceId = Convert.ToString(SelectedProjectId) + "|" + Convert.ToString(PortalSettings.AdministratorId) + "|" + Convert.ToString(DateTime.Now.ToUniversalTime());
//receiver.paymentSubType = null;
receiver.paymentType = "GOODS";
receiver.primary = true;
if (!String.IsNullOrEmpty(PRIMARY_RECEIVER_PHONE_NUMBER))
{
receiver.phone = new PhoneNumberType();new PhoneNumberType("001",PRIMARY_RECEIVER_PHONE_NUMBER);
}
if (!String.IsNullOrEmpty(PRIMARY_RECEIVER_EMAIL_ADDRESS))
{
receiver.email = PRIMARY_RECEIVER_EMAIL_ADDRESS;
}
receiverList.receiver.Add(receiver);
// Secondary Receiver
string receiverEmail = "";
string receiverPhone = VALID_PHONE_NUMBER;
String receiverUserName = MembershipServices.Business.SharedFunctions.GetUserNameEmail(PortalId, SelectedProject.ProjectOwnerID, MembershipServices.SharedEnums.DisplayNameFormat_Type.FullName, ref receiverEmail);
Receiver receiver2 = new Receiver(Decimal.Parse(this.txtPledgeAmount.Text.Trim()) * SECONDARY_RECEIVER_PERCENTAGE);
if (!String.IsNullOrEmpty(receiverPhone))
{
receiver2.phone = receiver.phone = new PhoneNumberType("001", receiverPhone);
}
if (!String.IsNullOrEmpty(receiverEmail))
{
receiver2.email = receiverEmail;
}
receiver2.primary = Boolean.Parse("false");
receiver2.invoiceId = Convert.ToString(SelectedProjectId) + "|" + Convert.ToString(SelectedProject.ProjectOwnerID) + "|" + Convert.ToString(DateTime.Now.ToUniversalTime()); ;
receiver2.paymentType = "GOODS";
receiverList.receiver.Add(receiver2);
String PortalAlias = PortalSettings.PortalAlias.HTTPAlias;
if (!PortalAlias.EndsWith("/"))
{
PortalAlias = PortalAlias + "/";
}
if (Request.IsSecureConnection)
{
PortalAlias = #"https://" + PortalAlias;
}
else
{
PortalAlias = #"http://" + PortalAlias;
}
string actionType = "PAY_PRIMARY";
PayRequest req = new PayRequest(new RequestEnvelope("en_US"), actionType,
PortalAlias + CANCEL_URL, SharedEnums.CurrencyCode_Type.USD.ToString(),
receiverList, PortalAlias + RETURN_URL);
req.ipnNotificationUrl = PortalAlias + IPN_NOTIFICATION_URL;
//(Optional) A note associated with the payment (text, not HTML).
// Maximum length: 1000 characters, including newline characters
if (!String.IsNullOrEmpty(txtPledgeMessage.Text.Trim()))
{
req.memo = txtPledgeMessage.Text.Trim();
}
else
{
req.memo = null;
}
// set optional parameters
//(Optional) Whether to reverse parallel payments if an error occurs with a payment.
//Allowable values are:
//true – Each parallel payment is reversed if an error occurs
//false – Only incomplete payments are reversed (default)
req.reverseAllParallelPaymentsOnError = false;
req.feesPayer = "EACHRECEIVER";
// Sender's email address
=req.senderEmail = SENDER_EMAIL_ADDRESS;
//(Optional) A unique ID that you specify to track the payment.
//Note: You are responsible for ensuring that the ID is unique.
//Maximum length: 127 characters
string trackingId = Convert.ToString(SelectedProjectId + "|" + Convert.ToString(SelectedUserId) + "|" + Convert.ToString(DateTime.Now.ToUniversalTime()));
req.trackingId = trackingId;
// All set. Fire the request
AdaptivePaymentsService service = new AdaptivePaymentsService();
PayResponse resp = null;
try
{
resp = service.Pay(req);
}
catch (System.Exception e)
{
Response.Write(e.Message);
return;
}
If you've worked through this or can spot the error, please let me know!
Thanks.
Removing the phone number fields returns a successful response. I'm not certain if phone number fields are not supposed to be available in a Delayed Chained Payment transaction. I'm going to have to reach out to the product team for Adaptive Payments and find out from them.
Edit: The phone number has to be a confirmed mobile one. The error you're getting is because the phone number field can also be used to define the receiver so you're actually attempting to define the receivers twice.
The request I tested with (the same as yours but has Sandbox e-mail addresses set) -
requestEnvelope.errorLanguage=en_US
actionType=PAY_PRIMARY
cancelUrl=http://localhost/ccc/ProgramsandServices/CommunityFundingInitiative/OopsSomethingWentWrong!.aspx
currencyCode=USD
feesPayer=EACHRECEIVER
ipnNotificationUrl=http://localhost/ccc/desktopmodules/UCU_ProjectManagement/PayPalIPN.aspx
receiverList.receiver(0).amount=10.00
receiverList.receiver(0).email=bending#bender.com
receiverList.receiver(0).primary=true
receiverList.receiver(0).invoiceId=51|1|6/16/2013 4:35:56 PM
receiverList.receiver(0).paymentType=GOODS
receiverList.receiver(1).amount=9.50
receiverList.receiver(1).email=stuff#stuffers.com
receiverList.receiver(1).primary=false
receiverList.receiver(1).invoiceId=51|1|6/16/2013 4:35:56 PM
receiverList.receiver(1).paymentType=GOODS
reverseAllParallelPaymentsOnError=false
senderEmail=testingAccess8x#paypal.com
returnUrl=http://localhost/ccc/ProgramsandServices/CommunityFundingInitiative/ThankYouforYourDonation.aspx
trackingId=51|0|6/16/2013 4:35:56 PM

Is that possible to generate unique Id for list item across site collection?

Ex: I have 10 sites and every site have 5 list. From site 1 i have adding one item in listX now id will be like "1" and creating another item in listB of 4th sub site so now id will "2"... So it has to go on like this how to achieve this?
I need to update this with all list item added event ? also how to get the latest id?
I have tried this code with custom forms it's work's cool, but thinking this may give concurrency issue
public static void ID()
{
if ((field.InternalName.Equals("Field1")))
{
{
string template;
using (SPSite site = new SPSite(SPContext.Current.Site.Url))
{
using (SPWeb web = site.RootWeb)
{
template = web.Properties["eydtemplate"].ToString();
}
}
if ("eydadvisory" == template)
{
SPListItemCollection items = _currentList.Items;
if (_currentList.ItemCount == 0)
{
webControl.Field.DefaultValue = (1).ToString();
}
else
{
SPQuery query = new SPQuery();
query.RowLimit = 1;
query.Query = " <OrderBy><FieldRef Name='" + field.InternalName + "' Ascending='FALSE' /></OrderBy>";
webControl.Field.DefaultValue = (Convert.ToInt64(_currentList.GetItems(query).Cast<SPListItem>().FirstOrDefault()[field.InternalName]) + 1).ToString();
}
}
}

Create class at runtime, serilize and de-serilize then cast to Interface froblem

Hi,
I have the following code :
public static object CreateTypedReport(string typeName, string inheritFrom)
{
DirectoryInfo dirInfo;
CSharpCodeProvider c = new CSharpCodeProvider();
CompilerParameters cp = new CompilerParameters();
foreach (Assembly asm in System.AppDomain.CurrentDomain.GetAssemblies())
{
if(!asm.FullName.StartsWith("ReportAssembly, Version=0.0.0.0"))
cp.ReferencedAssemblies.Add(asm.Location);
}
cp.CompilerOptions = "/t:library";
cp.GenerateInMemory = true;
dirInfo = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\MyApp\\ReportAssemblies\\");
if (!dirInfo.Exists)
dirInfo.Create();
cp.OutputAssembly = dirInfo.FullName + typeName + "Assembly";
cp.ReferencedAssemblies.Add(typeof(XtraReport).Assembly.Location);
//cp.OutputAssembly = typeName + "Assembly";
StringBuilder sb = new StringBuilder("");
sb.Append("using System;\n");
sb.Append("using MyNamespace.UI;\n");
sb.Append("namespace TypedReports { \n");
sb.Append("public class " + typeName + " : " + inheritFrom + "{ \n");
sb.Append("} \n");
sb.Append("}\n");
CompilerResults cr = c.CompileAssemblyFromSource(cp, sb.ToString());
if (cr.Errors.Count > 0)
{
MessageBox.Show("ERROR: " + cr.Errors[0].ErrorText, "Error evaluating cs code", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
return cr.CompiledAssembly.CreateInstance("TypedReports." + typeName);
}
This will create a class based on the typeName and inheritFrom parameters and then finally an object will be created and returned. inheritFrom will point at a class that implements IMyInterface.
It's possible to cast this object to a IMyInterface if it's needed.
When we then serialize and de-serialize this object we will not be able to cast it to IMyInterface anymore?
Why? And how could I solve it?
The problem was in the serialization och deserialization of the object. When this was changed it worked great. The solution is in a third party product so I can´t post it here.