You need to sign in to do that
Don't have an account?

Struggling with Test Class and Method does not exist errors
Sorry but I'm a complete newbie.
I have written a simple controller for a custom object which just allows me to return the objects in various formats to a Visualforce page for display.
This is the Controller code:-
public with sharing class NewsController {
public PageReference handleNewItemClick() {
PageReference pageRef= new PageReference('/apex/newsedit');
pageRef.setredirect(true);
return pageRef;
}
public News_Item__c[] getHeadlines() {
return [select Name, id, CreatedDate, CreatedBy.Name, Item__c from News_Item__c order by LastModifiedDate desc limit 3];
}
public News_Item__c[] getItems() {
return [select Name, id, CreatedDate, CreatedBy.Name, Item__c from News_Item__c];
}
public News_Item__c getNewsEntry() {
id id = ApexPages.currentPage().getParameters().get('id');
if (id == null)
return [select Name, id, CreatedDate, CreatedBy.Name, Item__c from News_Item__c order by CreatedDate desc limit 1];
else
return [select Name, id, CreatedDate, CreatedBy.Name, Item__c from News_Item__c where id = :ApexPages.currentPage().getParameters().get('id')];
}
}
First off, I'm not sure how or if I should be testing this (what should I aim to be testing as all the code does is return data to a VF page - no triggers, no data updates or insertions or anything?). But I've cobbled together a test class:-
@isTest
private class TestNewsController {
static testMethod void testNewsDisplay() {
News_Item__c[] items = new News_Item__c[] {
new News_Item__c(Name = 'Headline 1', Item__c = 'News item 1 test text'),
new News_Item__c(Name = 'Headline 2', Item__c = 'News item 2 test text'),
new News_Item__c(Name = 'Headline 3', Item__c = 'News item 3 test text'),
new News_Item__c(Name = 'Headline 4', Item__c = 'News item 3 test text')
};
insert items;
Test.startTest();
update items;
News_Item__c LastItem = new News_Item__c();
LastItem = NewsEntry();
Test.stopTest();
System.assert(LastItem.Name == 'Headline 4');
}
}
I get the Method does not exist error on the LastItem = NewsEntry(); line (I'm just trying to return a News_Item__c within Apex - I use {!NewsEntry} in the VF page without any problem.
So how should I be testing this controller (or shouldn't I bother)? and what syntax am I breaking with LastItem = NewsEntry(); ?
Thanks.
When you write NewsEntry() there's no way the language can figure out what you mean.
What you really want to do is invoke "getNewsEntry()" on the "NewsController" class right?
So you need:
- to create an instance of the class
- call the method
Just like you do when calling any class method in any language.
So for example, your test method should do something like:
NewsController nc = new NewsController();
News_Item__c lastItem = nc.getNewsEntry();
etc.
See the Test Methods and Visualforce Controllers section in An Introduction to Apex Code Test Methods
PS. You should also use System.assertEquals() instead of System.assert() when checking equality
Many thanks Jon - that's helpful. Although I understand the idea of OOL, most of my experience is in more primitive languages so the OOL syntax is new to me and not that well explained in the workbooks/examples (or maybe it's just me).
However, I'm still not fully understanding what's required for these tests: most of the examples in the Test Methods and Visualforce Controllers section in An Introduction to Apex Code Test Methods don't seem to use Test.startTest and Test.stopTest - are these only required when testing triggers?
The documentaion also says "Broadly speaking, you should test your custom business logic" - so since there is no custom logic in this case, does that mean no testing is required, and if so, does that have any implications on the magic 75% figure?
Your use of startTest and stopTest is great - continue using it.
Yes, you should always test. And don't stop at 75% - go much higher.
It's really about testing all logic -not just "business logic". Your controller has logic, and your test does a good job of testing the one method (ensuring that the most recently created item is returned). You shoudl test the other methods too :-)
PS. I've just noticed something weird.
You shouldn't do this:
That's fickle. What happens if you change the page name for example. I think you should rather do it like this:
Now the system can track that there's a dependency between the page and the controller (and won't let you delete the page, for example, without deleting the controller first).
Thanks again.
My use of startTest and stopTest might be great, but it is entirely mechanical and lacking in understanding. I've included update news within it, but I can't see it's doing anything given that the test data has already been inserted above!
Anyway, here's an improved test
@isTest
private class TestNewsController {
static testMethod void testNewsDisplay() {
News_Item__c[] news = new News_Item__c[] {
new News_Item__c(Name = 'Headline 1', Item__c = 'News item 1 test text'),
new News_Item__c(Name = 'Headline 2', Item__c = 'News item 2 test text'),
new News_Item__c(Name = 'Headline 3', Item__c = 'News item 3 test text'),
new News_Item__c(Name = 'Headline 4', Item__c = 'News item 4 test text')
};
insert news;
NewsController nc = new NewsController();
News_Item__c LastItem = nc.getNewsEntry();
News_Item__c[] Headlines = nc.getHeadlines();
News_Item__c[] Items = nc.getItems();
Test.startTest();
update news;
Test.stopTest();
System.assertEquals(LastItem.Name,'Headline 1');
for (Integer i=0; i < 3; i++) {
System.assertEquals(Headlines[i].Name,'Headline '+(i+1));
}
for (Integer i=0; i < 4; i++) {
System.assertEquals(Items[i].Name,'Headline '+(i+1));
}
}
}
How would I initialise ApexPages.currentPage().getParameters().get('id') in a test method, to test that line of the controller?
Use
See
http://www.salesforce.com/us/developer/docs/pages/Content/pages_controller_error_handling.htm
One more problem:
Test code is now:-
@isTest
private class TestNewsController {
static testMethod void testNewsDisplay() {
// Setup some News Item test data
News_Item__c[] news = new News_Item__c[] {
new News_Item__c(Name = 'Headline 1', Item__c = 'News item 1 test text'),
new News_Item__c(Name = 'Headline 2', Item__c = 'News item 2 test text'),
new News_Item__c(Name = 'Headline 3', Item__c = 'News item 3 test text'),
new News_Item__c(Name = 'Headline 4', Item__c = 'News item 4 test text')
};
insert news;
// Instantiate a new controller
NewsController nc = new NewsController();
Test.startTest();
update news;
Test.stopTest();
// Test handleNewItemClick method
PageReference NewItem = nc.handleNewItemClick();
System.assertEquals(NewItem,Page.newsedit);
// Test getNewsEntry method with NULL page id
News_Item__c DefaultLastItem = nc.getNewsEntry();
System.assertEquals(DefaultLastItem.Name,'Headline 1');
// Test getNewsEntry method with valid page id
string pageid = news[3].id;
ApexPages.currentPage().getParameters().put('id', pageid);
News_Item__c LastItem = nc.getNewsEntry();
System.assertEquals(LastItem.Name,'Headline 4');
// Test getHeadlines method
News_Item__c[] Headlines = nc.getHeadlines();
for (Integer i=0; i < 3; i++) {
System.assertEquals(Headlines[i].Name,'Headline '+(i+1));
}
// Test getItems method
News_Item__c[] Items = nc.getItems();
for (Integer i=0; i < 4; i++) {
System.assertEquals(Items[i].Name,'Headline '+(i+1));
}
}
}
which would give me 100% coverage if only it didn't fail with an Assert error
19:34:46.740|FATAL_ERROR|System.AssertException: Assertion Failed: Expected: System.PageReference[/apex/newsedit], Actual: System.PageReference[/apex/newsedit]
... except that what it expects and the actual appear to be identical.
What's the code that's being tested now look like?
public with sharing class NewsController {
public PageReference handleNewItemClick() {
PageReference pageRef= Page.newsedit;
pageRef.setredirect(true);
return pageRef;
}
public News_Item__c[] getHeadlines() {
return [select Name, id, CreatedDate, CreatedBy.Name, Item__c from News_Item__c order by LastModifiedDate desc limit 3];
}
public News_Item__c[] getItems() {
return [select Name, id, CreatedDate, CreatedBy.Name, Item__c from News_Item__c order by LastModifiedDate desc];
}
public News_Item__c getNewsEntry() {
id id = ApexPages.currentPage().getParameters().get('id');
if (id == null)
return [select Name, id, CreatedDate, CreatedBy.Name, Item__c from News_Item__c order by LastModifiedDate desc limit 1];
else
return [select Name, id, CreatedDate, CreatedBy.Name, Item__c from News_Item__c where id = :ApexPages.currentPage().getParameters().get('id')];
}
}
You would think that this would work:
Many thanks Steve, that worked for me.