How to use local variable in spock test case in another class? - variables

I want to use the "dashVer" in StartupTest.groovy in Zip.groovy, but "dashVer" in Zip.groovy return in "null". For detail, please read below, thank you very much!!!!
StartupTest.groovy
class StartupTest extends Specification {
String dashVer
void updateGlobalString(String dashVersion){
dashVer=dashVersion
}
def 'Start_test'() {
setup:
.......
when: 'Test started'
String dashVersion= new GetDashVer().Get_dash_ver().toString()
println(dashVersion) //Eg.the result is 3.3.3 return from GetDashVer class sucessfully
updateGlobalString(dashVersion)
and:
...
then:
...
}
}
Zip.groovy
class ZipUploadSlack {
//Attempt 1
StartupTest test = new StartupTest()
String dashVer111 = test.updateGlobalString()
//Attept 2
//StartupTest test = new StartupTest()
//String dashVer111 = test.dashVer
def 'Zip'(){
println(dashVer111) //This should be return in 3.3.3, but it is "null" for now for both attepts
}
}

#Jacob Aae Mikkelsen, thanks for the advice. Seems static variable working.
Just tried with below:
Startuptest.groovy
class StartupTest extends Specification {
static String dashbVer
static Integer errorCount
String updateGlobalString(String dashVersion){
dashVer=dashVersion
return dashVer
}
Integer updateGlobalInteger(Integer errorC){
errorCount=errorC
return errorCount
}
void updateGlobalString(String dashVersion){
dashVer=dashVersion
}
def 'Start_test'() {
setup:
.......
when: 'Test started'
String dashVersion= new GetDashVer().Get_dash_ver().toString()
println(dashVersion) //Eg.the result is 3.3.3 return from GetDashVer class sucessfully
updateGlobalString(dashVersion)
and:
...
then: 'No error log found'
def error = dash.logFinder.search(/\(ERROR\)/)
error.isEmpty() //Let says it is true, it is empty as no error found
int errorC = error.size() as Integer //.size is using List.java, #return the number of elements in this list
println(errorC) //Here return as 0 as expected
updateGlobalInteger(errorC) // Here return with error, "condition not satisfied groovy"
}
}
Zip.groovy
class ZipUploadSlack {
//Obtain dashVer
StartupTest test = new StartupTest()
String dashVer111 = test.dashVer
def 'Zip'(){
println(dashVer111) //This can return correct dashVer now
}
}
My new question is why there is "condition not satisfied groovy" error when executing updateGlobalInteger(errorC)? errorC is integer and the updateGlobalInteger function is returning a integer, why failed? Thanks!!!!

Related

HTTP end point property string starts with "is" will get omit [duplicate]

This might be a duplicate. But I cannot find a solution to my Problem.
I have a class
public class MyResponse implements Serializable {
private boolean isSuccess;
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
}
Getters and setters are generated by Eclipse.
In another class, I set the value to true, and write it as a JSON string.
System.out.println(new ObjectMapper().writeValueAsString(myResponse));
In JSON, the key is coming as {"success": true}.
I want the key as isSuccess itself. Is Jackson using the setter method while serializing? How do I make the key the field name itself?
This is a slightly late answer, but may be useful for anyone else coming to this page.
A simple solution to changing the name that Jackson will use for when serializing to JSON is to use the #JsonProperty annotation, so your example would become:
public class MyResponse implements Serializable {
private boolean isSuccess;
#JsonProperty(value="isSuccess")
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
}
This would then be serialised to JSON as {"isSuccess":true}, but has the advantage of not having to modify your getter method name.
Note that in this case you could also write the annotation as #JsonProperty("isSuccess") as it only has the single value element
I recently ran into this issue and this is what I found. Jackson will inspect any class that you pass to it for getters and setters, and use those methods for serialization and deserialization. What follows "get", "is" and "set" in those methods will be used as the key for the JSON field ("isValid" for getIsValid and setIsValid).
public class JacksonExample {
private boolean isValid = false;
public boolean getIsValid() {
return isValid;
}
public void setIsValid(boolean isValid) {
this.isValid = isValid;
}
}
Similarly "isSuccess" will become "success", unless renamed to "isIsSuccess" or "getIsSuccess"
Read more here: http://www.citrine.io/blog/2015/5/20/jackson-json-processor
Using both annotations below, forces the output JSON to include is_xxx:
#get:JsonProperty("is_something")
#param:JsonProperty("is_something")
When you are using Kotlin and data classes:
data class Dto(
#get:JsonProperty("isSuccess") val isSuccess: Boolean
)
You might need to add #param:JsonProperty("isSuccess") if you are going to deserialize JSON as well.
EDIT: If you are using swagger-annotations to generate documentation, the property will be marked as readOnly when using #get:JsonProperty. In order to solve this, you can do:
#JsonAutoDetect(isGetterVisibility = JsonAutoDetect.Visibility.NONE)
data class Dto(
#field:JsonProperty(value = "isSuccess") val isSuccess: Boolean
)
You can configure your ObjectMapper as follows:
mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
#Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
{
if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class)
&& method.getName().startsWith("is")) {
return method.getName();
}
return super.nameForGetterMethod(config, method, defaultName);
}
});
I didn't want to mess with some custom naming strategies, nor re-creating some accessors.
The less code, the happier I am.
This did the trick for us :
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
#JsonIgnoreProperties({"success", "deleted"}) // <- Prevents serialization duplicates
public class MyResponse {
private String id;
private #JsonProperty("isSuccess") boolean isSuccess; // <- Forces field name
private #JsonProperty("isDeleted") boolean isDeleted;
}
Building upon Utkarsh's answer..
Getter names minus get/is is used as the JSON name.
public class Example{
private String radcliffe;
public getHarryPotter(){
return radcliffe;
}
}
is stored as { "harryPotter" : "whateverYouGaveHere" }
For Deserialization, Jackson checks against both the setter and the field name.
For the Json String { "word1" : "example" }, both the below are valid.
public class Example{
private String word1;
public setword2( String pqr){
this.word1 = pqr;
}
}
public class Example2{
private String word2;
public setWord1(String pqr){
this.word2 = pqr ;
}
}
A more interesting question is which order Jackson considers for deserialization. If i try to deserialize { "word1" : "myName" } with
public class Example3{
private String word1;
private String word2;
public setWord1( String parameter){
this.word2 = parameter ;
}
}
I did not test the above case, but it would be interesting to see the values of word1 & word2 ...
Note: I used drastically different names to emphasize which fields are required to be same.
You can change primitive boolean to java.lang.Boolean (+ use #JsonPropery)
#JsonProperty("isA")
private Boolean isA = false;
public Boolean getA() {
return this.isA;
}
public void setA(Boolean a) {
this.isA = a;
}
Worked excellent for me.
If you are interested in handling 3rd party classes not under your control (like #edmundpie mentioned in a comment) then you add Mixin classes to your ObjectMapper where the property/field names should match the ones from your 3rd party class:
public class MyStack32270422 {
public static void main(String[] args) {
ObjectMapper om3rdParty = new ObjectMapper();
om3rdParty .addMixIn(My3rdPartyResponse.class, MixinMyResponse.class);
// add further mixins if required
String jsonString = om3rdParty.writeValueAsString(new My3rdPartyResponse());
System.out.println(jsonString);
}
}
class MixinMyResponse {
// add all jackson annotations here you want to be used when handling My3rdPartyResponse classes
#JsonProperty("isSuccess")
private boolean isSuccess;
}
class My3rdPartyResponse{
private boolean isSuccess = true;
// getter and setter here if desired
}
Basically you add all your Jackson annotations to your Mixin classes as if you would own the class. In my opinion quite a nice solution as you don't have to mess around with checking method names starting with "is.." and so on.
there is another method for this problem.
just define a new sub-class extends PropertyNamingStrategy and pass it to ObjectMapper instance.
here is a code snippet may be help more:
mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
#Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
String input = defaultName;
if(method.getName().startsWith("is")){
input = method.getName();
}
//copy from LowerCaseWithUnderscoresStrategy
if (input == null) return input; // garbage in, garbage out
int length = input.length();
StringBuilder result = new StringBuilder(length * 2);
int resultLength = 0;
boolean wasPrevTranslated = false;
for (int i = 0; i < length; i++)
{
char c = input.charAt(i);
if (i > 0 || c != '_') // skip first starting underscore
{
if (Character.isUpperCase(c))
{
if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_')
{
result.append('_');
resultLength++;
}
c = Character.toLowerCase(c);
wasPrevTranslated = true;
}
else
{
wasPrevTranslated = false;
}
result.append(c);
resultLength++;
}
}
return resultLength > 0 ? result.toString() : input;
}
});
The accepted answer won't work for my case.
In my case, the class is not owned by me. The problematic class comes from 3rd party dependencies, so I can't just add #JsonProperty annotation in it.
To solve it, inspired by #burak answer above, I created a custom PropertyNamingStrategy as follow:
mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
#Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
{
if (method.getParameterCount() == 1 &&
(method.getRawParameterType(0) == Boolean.class || method.getRawParameterType(0) == boolean.class) &&
method.getName().startsWith("set")) {
Class<?> containingClass = method.getDeclaringClass();
String potentialFieldName = "is" + method.getName().substring(3);
try {
containingClass.getDeclaredField(potentialFieldName);
return potentialFieldName;
} catch (NoSuchFieldException e) {
// do nothing and fall through
}
}
return super.nameForSetterMethod(config, method, defaultName);
}
#Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
{
if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class)
&& method.getName().startsWith("is")) {
Class<?> containingClass = method.getDeclaringClass();
String potentialFieldName = method.getName();
try {
containingClass.getDeclaredField(potentialFieldName);
return potentialFieldName;
} catch (NoSuchFieldException e) {
// do nothing and fall through
}
}
return super.nameForGetterMethod(config, method, defaultName);
}
});
Basically what this does is, before serializing and deserializing, it checks in the target/source class which property name is present in the class, whether it is isEnabled or enabled property.
Based on that, the mapper will serialize and deserialize to the property name that is exist.

Salesforce Apex Test Class Failing on saving of an account

having a little trouble figuring out why my test class is returning System.DmlException: Upsert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Name]: [Name]
I have required field Name on the Account object in SFDC, but Since I'm mocking the Account with a Name attribute shouldn't my test class save function work?
Below is my Apex Class
public with sharing class QuoteAccountController {
// Define VariableType and VariableName
public ApexPages.StandardController standardContactController;
public Account Account{get;set;}
public Contact Contact{get;set;}
public Account selectedAccount{get;set;}
public Boolean displayProjectInformation{get;set;}
public Boolean projectNameError{get;set;}
public Boolean projectValidationsPassed{get;set;}
//Page Constructor/Initializer
public QuoteAccountController(ApexPages.StandardController StandardController) {
Account = new Account();
Contact = new Contact();
displayProjectInformation = true;
projectNameError = false;
projectValidationsPassed = true;
}
public pageReference save() {
projectValidations();
if (projectValidationsPassed) {
upsert Account;
Contact.accountId = Account.id;
upsert Contact;
Contact = new Contact();
Account = new Account();
ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.CONFIRM,'Record Created Successfully.Thank you!'));
return null;
} else {
return null;
}
}
public void projectValidations(){
if (Account.Subscription_Type__c == 'Project' && String.isBlank(Account.Project_Name__c)) {
projectValidationsPassed = false;
ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Project Name is required field'));
} else if (Account.Subscription_Type__c == 'Project' && String.isBlank(Account.Project_Type__c)) {
projectValidationsPassed = false;
ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Project Type is required field'));
} else if (Account.Subscription_Type__c == 'Project' && Account.Project_Start_Date__c == null) {
projectValidationsPassed = false;
ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Project Start Date is required field'));
} else if (Account.Subscription_Type__c == 'Project' && Account.Project_End_Date__c == null){
projectValidationsPassed = false;
ApexPages.AddMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Project End Date is required field'));
} else {
projectValidationsPassed = true;
}
}
Below is my Apex Test Class
#isTest
public class QuoteAccountControllerTest {
private static testmethod void testSave() {
Quote quote = new Quote();
Account testAcc = new Account();
Contact con = new Contact();
ApexPages.StandardController stdCont = new ApexPages.StandardController(testAcc);
QuoteAccountController quoteAccCont = new QuoteAccountController(stdCont);
PageReference page = new PageReference('/apex/zqu_QuoteAccount?quoteType=Subscription&stepNumber=1');
Test.setCurrentPage(page);
testAcc.Project_Name__c = 'Project Name';
testAcc.Name = 'Test Account';
testAcc.Project_Start_Date__c = Date.today();
testAcc.Project_End_Date__c = Date.today().addDays(2);
testAcc.Project_Type__c = 'Convention Center';
testAcc.Region__c = 'US';
testAcc.Subscription_Type__c = 'User';
Test.startTest();
quoteAccCont.save();
Test.stopTest();
}
}
Thanks!
Edit: Error message below.
System.DmlException: Upsert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Name]: [Name]
I don't have too much background in Salesforce but I believe that you need to insert the objects that you are creating with new before Test.startTest();
If this fails too, try to use System.debug() in your Apex Test class and use the Salesforce developer console and their logs to follow your error. Maybe this helps. Good luck!
You are trying to upsert an account. Upsert(Update/Insert) call would look for Id in the account you are upserting. If Id is found Upsert would work fine else it would Insert. So in your case it is trying to insert not update. That is why Name is mandatory.
Figured out solution. Need to assign the Account and Contact to the Controller. See modified code below.
#isTest
public class QuoteAccountControllerTest {
private static testmethod void testSave() {
Quote quote = new Quote();
ApexPages.StandardController stdCont = new ApexPages.StandardController(testAcc);
QuoteAccountController quoteAccCont = new QuoteAccountController(stdCont);
quoteAccCont.Account = new Account(ATTRIBUTES_HERE);
quoteAccCont.Contact = new Contact(ATTRIBUTES_HERE
PageReference page = new PageReference('/apex/zqu_QuoteAccount?quoteType=Subscription&stepNumber=1');
Test.setCurrentPage(page);
Test.startTest();
quoteAccCont.save();
Test.stopTest();
}
}

how to access session in integration test in grails?

In my project, i set session.loggedInUser in login controller. But during integration test , we dont use login controller. So i have set value for session.loggedInUser. But i couldn't use session in that place. How can i use session in integration Test. Give some solution for this. thank you in advance
class MaritalStatusIntegrationTests {
#Test
void testCategoryAudit() {
RequestContextHolder.currentRequestAttributes().session.loggedInUser="Anantha"
def category = new Category(name:"Single")
category.save(flush:true)
assert CategoryAudit.count() == 1
category.name="Married"
category.save(flush:true)
assert CategoryAudit.count() == 2
}
}
Category.groovy:
class Category {
static constraints = {
name blank:false
}
String name
//Auditing
static auditable = false
def onSave = {
new CategoryAudit(this,'Insert').save(failOnError:true)
}
}
CategoryAudit.groovy:
import org.springframework.web.context.request.RequestContextHolder
class CategoryAudit {
String name
String operation
String doneBy
Date txnDate
def CategoryAudit(){}
def CategoryAudit(Category category , String operation) {
this.name = category.name
this.operation = operation
this.doneBy = RequestContextHolder.currentRequestAttributes().session.loggedInUser
this.txnDate = new Date()
}
}
No such property: RequestContextHolder for class:
com.vasco.gs.MaritalStatusIntegrationTest.
Just to clean up, according to the OP, it was missing the import for RequestContextHolder.

How to get all visible variables for a certain method in JDT

I want to develop an Eclipse plug-in which get all visible variables for a specific method.
For example:
public class testVariable {
String test1;
Object test2;
void method_test1(){
int test3,test4;
}
void method_test2(){
int test5,test6;
//get variable here!!!!
}
}
I just want to get visible variable is: test1, test2,test5,test6 in method method_test2. What can I do?
Actually, JDT can be used outside of a plug-in, i.e., it can be used in a stand-alone Java application.
The following code can return the variables you want:
public static void parse(char[] str) {
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setSource(str);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
final CompilationUnit cu = (CompilationUnit) parser.createAST(null);
cu.accept(new ASTVisitor() {
public boolean visit(VariableDeclarationFragment var) {
System.out.println("variable: " + var.getName());
return false;
}
public boolean visit(MethodDeclaration md) {
if (md.getName().toString().equals("method_test2")) {
md.accept(new ASTVisitor() {
public boolean visit(VariableDeclarationFragment fd) {
System.out.println("in method: " + fd);
return false;
}
});
}
return false;
}
});
}
The output is:
variable: test1
variable: test2
in method: test5
in method: test6
Check out more examples at JDT tutorials.

Struts2 more than one action in one class

I'm using Struts2. I have two web forms that have the same code. I would like to eliminate one form. Here is the structure of my Struts project.
\Web Pages
form.jsp
\WEB-INF
\Content
error.jsp
form.jsp
success.jsp
\Source Packages
\action
MyAction.java
MyAction.java
package action;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.*;
public class MyAction extends ActionSupport {
#Action(value = "foo", results = {
#Result(name = "input", location = "form.jsp"),
#Result(name = "success", location = "success.jsp"),
#Result(name = "error", location = "error.jsp")
})
public String execute() throws Exception {
if (user.length() == 1) {
return "success";
} else {
return "error";
}
}
private String user = "";
public void validate() {
if (user.length() == 0) {
addFieldError("user", getText("user required"));
}
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
}
I tried to eliminate form.jsp under \Web Pages by adding a new action method to MyAction.java.
#Action(value="bar", results = {
#Result(name = "success", location = "form.jsp"),
})
public String another() {
return "success";
}
But I got the following error when I go to http : //localhost .../bar.action
HTTP Status 404 - No result defined for action action.MyAction and result input
Your MyAction has an implementation of validate(), which means it is validation aware.
What's happening is that you're calling another, but validate() is kicking in (as it's in the interceptor stack). Validation is failing, and therefore sending to INPUT result, which is not defined in another.
You should
Add #SkipValidation to the another method if you don't want validation there
Add the INPUT result to another() if you want a default input result
On a more general note, when you get that kind of error (No result defined for action X and result input) it usually means you're either having validation errors, parameter population errors (eg: an exception in preparable).