I am having a pesky error testing this piece of code.Not sure what I am doing wrong. I have tested standard controllers before but not the getSelectedMethod
Error:
Constructor not defined:[myClass].(ApexPages.StandardController)
public class MyClass{
public List<Web__c> postings {get;set;}
public static final String POSTINGSTATUS = 'Yes';
public MyClass (ApexPages.StandardSetController controller) {
List<Web__c> selectedWeb = (List<Web__c>) controller.getSelected();
postings = [Select Id, Name,
FROM Web___c Where Id IN: selectedWeb
AND Date__c != null
AND Date__c > today];
}
}
My Test Class
private class myTestClass {
static testMethod void WebTest() {
List <Web__c> posting = helper.createWeb(4);
insert posting;
Test.startTest();
PageReference pageRef = Page.VFPAGE;
Test.setCurrentPage(pageRef);
ApexPages.StandardController sc = new ApexPages.standardController(posting[0]);
myClass JPC = new myClass(sc);
sc.setSelected(posting);
Test.stopTest();
}
new ApexPages.standardController(posting[0]) looks wrong to me.
It should likely be new ApexPages.StandardSetController(posting[0]) if you want to create a new instance of ApexPages.StandardSetController, or just ApexPages.standardController(posting[0]) (without the new) if it's a static method that returns such an instance.
BTW: you should state what error you get and where in the code it occurs when asking such a question, as figuring it out without that information is pretty hard. I just found this by chance, I'd asked for that information otherwise.
Related
I'm trying to write unit test against a class. I can't change the class, but I think it's possible to test using reflection. I just don't know how to do it. Here's the class:
public class MyClass extends AnotherClass implements TheInterface
{
private enum SomeTypes
{
SAMPLE01, SAMPLE02, SAMPLE03
}
private CircularList<SomeTypes> someTypesList;
Date date= new Date();
private SomeOtherClassProcessor01 someOtherClassProcessor01;
private SomeOtherClassProcessor02 someOtherClassProcessor02;
private SomeOtherClassProcessor03 someOtherClassProcessor03;
public Properties initialize (Properties properties) throws Exception
{
Properties propertiesToReturn = super.initialize(properties);
someTypesList = new CircularList<SomeTypes> (Arrays.asList(SomeTypes.values()));
someOtherClassProcessor01 = new SomeOtherClassProcessor01();
someOtherClassProcessor02 = new SomeOtherClassProcessor02();
someOtherClassProcessor03 = new SomeOtherClassProcessor03();
return propertiesToReturn;
}
#Override
public void get(ImportedClass someParams) throws Exception
{
SomeTypes types = someTypesList.getFirstAndRotate();
switch(types)
{
case SAMPLE01:
someOtherClassProcessor01.doSomething(someParams, date);
break;
case SAMPLE02:
someOtherClassProcessor02.doSomething(someParams, date);
break;
case SAMPLE03:
someOtherClassProcessor03.doSomething(someParams, date);
break;
default:
throw new IllegalArgumentException("This " + types + " was not implemented.");
}
}
}
For my test this is what I have so far... not sure how to actually do it.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class TestingMyClass
{
MyClass mockMyClass;
SomeOtherClassProcessor01 someOtherClassProcessor01;
SomeOtherClassProcessor02 someOtherClassProcessor02;
SomeOtherClassProcessor03 someOtherClassProcessor03;
Date date;
#Before
public void initialize () throws Exception
{
mockMyClass = spy(new MyClass());
mockSomeOtherClassProcessor01 = mock(SomeOtherClassProcessor01.class);
mockSomeOtherClassProcessor02 = mock(SomeOtherClassProcessor02.class);
mockSomeOtherClassProcessor03 = mock(SomeOtherClassProcessor03.class);
}
#Test
public void testingGet() throws Exception
{
date = new Date();
//this is where I'm stuck
Whitebox.setInternalState(mockMyClass, "someOtherClassProcessor01", mockSomeOtherClassProcessor01);
}
}
Would it be possible to use whitebox for this? I need to make sure that there's a call inside the getter for those objects. Should I try something like when(someOtherClassProcessor01.doSomething(any(), date)).thenReturn(true)? Please let me know if you need more details.
edit: is even possible to mock private enum SomeTypes?
One option is to substitute your own (mocked) implementations of SomeOtherClassProcessor into MyClass using reflection:
MyClass myClass = new MyClass();
SomeOtherProcessor01 mockProcessor01 = mock(SomeOtherProcessor01.class);
// reflection bit: find the field by its name
// handle NoSuchFieldException
Field someProcessorField = MyClass.getDeclaredField("someOtherProcessor01");
// the field is declared as private, so make it accessible in order to work with it
someProcessorField.setAccessible(true);
// now set your mocked processor into the field.
// First argument is the object to change; second argument - new value for the field
someProcessorField.set(myClass, mockProcessor01);
PS. Using PowerMock and/or reflection is surrender to bad design (as per Timothy :). You should not be depending on code you that isn't already well-tested, and if it is, you shouldn't try to test it again. Suppose your testing actually reveals a bug - how would you fix it if you don't control the code? Suppose Java 11 becomes a thing and prohibits your use of reflection. Suppose the code you're testing changes and the fields get renamed - with reflection, you don't have compile-time safety... List of potential issues goes on
I got about 6 classes that are doing 'almost' the same with different values. I'll give two classes and an example below and then describe what i'm doing.
public class AttributeRangeRule implements Template {
#Override
public String writeTemplate(BusinessRule businessRule) throws Exception {
String link = TemplateReader.getInstance().getLinkToQuery(businessRule.getBusinessRuleTypeCode());
String template = TemplateReader.getInstance().readQuery(link);
ST templateFixer = new ST(template);
templateFixer.add("code", businessRule.getBusinessRuleTypeCode());
templateFixer.add("attribute_table", businessRule.getListOfTables().get(0).getName());
templateFixer.add("operator", businessRule.getOperator().getName());
templateFixer.add("range_min", businessRule.getListOfValues().get(0).getValue());
templateFixer.add("range_max", businessRule.getListOfValues().get(1).getValue());
templateFixer.add("attribute_column", businessRule.getListOfColumns().get(0).getName());
templateFixer.add("error", businessRule.getErrorMessage());
templateFixer.add("GreaterOrEqual", ">=");
templateFixer.add("LessOrEqual", "<=");
templateFixer.add("LessThen", "<");
templateFixer.add("GreaterThen", ">");
String templateDLL = templateFixer.render();
return templateDLL;
}
}
public class AttributeCompareRule implements Template {
#Override
public String writeTemplate(BusinessRule businessRule) throws Exception {
String link = TemplateReader.getInstance().getLinkToQuery(businessRule.getBusinessRuleTypeCode());
String template = TemplateReader.getInstance().readQuery(link);
ST templateFixer = new ST(template);
templateFixer.add("code", businessRule.getBusinessRuleTypeCode());
templateFixer.add("attribute_table", businessRule.getListOfTables().get(0).getName());
templateFixer.add("operand", businessRule.getOperator().getName());
templateFixer.add("compare_with", businessRule.getListOfValues().get(0).getValue());
templateFixer.add("error", businessRule.getErrorMessage());
String templateDLL = templateFixer.render();
return templateDLL;
}
}
templateFixer.add("code..") is for example duplicate. They are written the same in both classes but the value is different.
I have different classes with different implementation of the method writeTemplate(). As you can see AttributeRangeRule is different from AttributeCompareRule. This code is writting a query for me. Intellij is telling me that the code is duplicate even if the values arent unique. I have no idea how to solve this issue. How can i solve this issue, since duplicate code isnt the best to have in your code. Thanks in advance.
You should try to take advantage of OOPS concepts here and use inheritance here
You can create a base class named AttributeRule that overrides writeTemplate() method and put all the redundant code in there and have this class be extended by your subclasses i.e. AttributeCompareRule and AttributeCompareRule
Here's the conceptual idea and some snippets
public class AttributeRule implements Template {
#Override
public String writeTemplate(BusinessRule businessRule) throws Exception {
String link = TemplateReader.getInstance().getLinkToQuery(businessRule.getBusinessRuleTypeCode());
String template = TemplateReader.getInstance().readQuery(link);
ST templateFixer = new ST(template);
templateFixer.add("code", businessRule.getBusinessRuleTypeCode());
templateFixer.add("attribute_table", businessRule.getListOfTables().get(0).getName());
}
}
public class AttributeCompareRule extends AttributeRule {
#Override
public String writeTemplate(BusinessRule businessRule) throws Exception {
super.writeTemplate(rule);
// Custom class code here
templateFixer.add("operand", businessRule.getOperator().getName());
templateFixer.add("compare_with", businessRule.getListOfValues().get(0).getValue());
templateFixer.add("error", businessRule.getErrorMessage());
String templateDLL = templateFixer.render();
return templateDLL;
}
}
public class AttributeRangeRule extends AttributeRule {
super.writeTemplate(rule);
// Custom class code here
}
I have a Java service which has few things injected by Guice.
public class RecoveryServiceImpl implements RecoveryService {
#Inject
public RecoveryServiceImpl(SessionInstanceCache sessionInstanceCache, AttendeeCache attendeeCache, MessagingStreamConfiguration messagingConfig) {
this.sessionInstanceCache = sessionInstanceCache;
this.attendeeCache = attendeeCache;
this.messagingConfig = messagingConfig;
}
#Override
public SessionInstanceData recoverSessionInstance(SessionInstanceDto sessionInstance) {
SessionInstanceData sessionInstanceData = SessionInstanceHelper.recoverSessionInstance(sessionInstance);
if (sessionInstanceData.getDeepstreamServerKey() == null) {
String dsKey = SessionInstanceHelper.pickRandomDeepstreamServerKey(
sessionInstanceData, messagingConfig);
And this does:
public static String pickRandomDeepstreamServerKey(
SessionInstanceData sessionInstanceData, MessagingStreamConfiguration dsConfig) {
// NPE occurs here
List<String> dsKeys = new ArrayList(dsConfig.getBaseUrls().keySet());
This is tested with Spock.
I added the messagingConfig and now I am struggling making it mocked in a Spock test:
class RecoveryServiceImplTest extends Specification {
...
MessagingStreamConfiguration msgConfig = Mock(MessagingStreamConfiguration);
RecoveryService recoveryService = new RecoveryServiceImpl(sessionInstanceCache, attendeeCache, msgConfig);
def "Recover session instance"() {
...
def dsMap = new HashMap<String, URL>();
dsMap.put("ds1", new URL("http://ilovemocking.com/"));
when:
msgConfig.getBaseUrls() >> dsMap;
//msgConfig.getBaseUrls().keySet() >> new HashSet(){{add("ds1")}};
recoveryService.recoverSessionInstance(sessionInstanceDto)
In the call to recoverSessionInstance(), I get a NPE because getBaseUrls() returns null.
I have tried other way, instantiating the msgConfig as a normal object (AKA "stubbing"), but same result.
How should I make Spock Mock to return the dsMap instead of null?
In the end, it was some issue with missing method in a dependency .jar (compared to what I saw as code). The NPE was coming from the Mock proxy rather than the expression itself. However it was hard to see in the stacktrace full of reflections.
I will delete the question in a while.
I am new to Java and I have failed to find anything about this case.
I am basically trying to pass this array called vakken to a new class called Vak,
Vak expects to receive a String and a int.
Vak[] vakken = new Vak[1];
vakken[0] = new Vak("Test",3);
Vak vak = new Vak(vakken[0]);
Whenever I try the code above I get this error.
Exception in thread "main" java.lang.UnsupportedOperationException: Not supported yet.
at ectsmonitor2.Vak.<init>(Vak.java:24)
at ectsmonitor2.ECTSmonitor2.main(ECTSmonitor2.java:27)
Java Result: 1
Vak.class
public class Vak {
public String naam;
public int teVerdienenEcts;
public Vak(String vakNaam, int vakTeVerdienenEcts){
naam = vakNaam;
teVerdienenEcts = vakTeVerdienenEcts;
}
}
You haven't actually coded your constructor that takes a Vak yet, you made it throw UnsupportedOperationException. Put some code in the constructor e.g.
public Vak(Vak v) {
this(v.naam, v.teVerdienenEcts);
}
This line wont work for sure
Vak vak = new Vak(vakken[0]);//IDE will display error message here
Because you have no such constructor for this.
Create a new constructor that takes an object of its own type.
Similar to this:
public Vak(Vak anObject){
//do stuffs here
}
These type of constructors are called copy constructors
And generally you won't want your attributes to be public. Make them private.
I have the following Class
public class Booking{
public String name;
public String comment;
public String session;
public void test(){
this.name = "hi";
}
}
I instrument it using the following:
cc.instrument(new ExprEditor(){
public void edit(FieldAccess arg) throws CannotCompileException {
if (arg.isWriter()) {
StringBuffer code = new StringBuffer();
code.append("$0.");
code.append(arg.getFieldName());
code.append("=$1.toUpperCase();");
arg.replace(code.toString());
}
}
});
Now when I call this:
Booking b = new Booking();
b.name = "hello";
System.out.println(b.name); // Edited correction
b.test();
System.out.println(b.name);
Gives me
hello // Externally, doesn't.
HI // Internally, works as expected
What am I missing? It just seems like one of those things I should be able to accomplish easily.
Please don't tell me I have to do a blanket "fieldAccess.replace" on all classes? O.O
Your example code fragment that contains the statement b.name = "hello"; isn't being instrumented, hence the value it writes is not converted to uppercase. An ExprEditor can only transform the field access from classes that are instrumented by it. If you want every write to the 'name' field converted to uppercase, you will have to instrument every class that contains a write statement for that field.