function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Patrick DixonPatrick Dixon 

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.

Jon Mountjoy_Jon Mountjoy_

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

Patrick DixonPatrick Dixon

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?

Jon Mountjoy_Jon Mountjoy_

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 :-)

 

 

Regards,
Jon

 

 

PS. I've just noticed something weird.

You shouldn't do this:

 

PageReference pageRef= new PageReference('/apex/newsedit');

That's fickle.  What happens if you change the page name for example.  I think you should rather do it like this:

 

PageReference pageRef= Page.newsedit;

 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).

 

 

 

 

Patrick DixonPatrick Dixon

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?

Jon Mountjoy_Jon Mountjoy_

Use

 

ApexPages.currentPage().getParameters().put('qp', 'yyyy');

 

 

See

http://www.salesforce.com/us/developer/docs/pages/Content/pages_controller_error_handling.htm

 

Patrick DixonPatrick Dixon

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.

Jon Mountjoy_Jon Mountjoy_

What's the code that's being tested now look like?

Patrick DixonPatrick Dixon

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')];
      }
}

SteveBowerSteveBower

You would think that this would work:

 

 

PageReference x = Page.Item_Distribution_Management;
PageReference y = Page.Item_Distribution_Management;
system.assertEquals(x,y);
However it doesn't you have to use:
system.assertEquals(x.getUrl(), y.getUrl());
Best, Steve.

 

Patrick DixonPatrick Dixon

Many thanks Steve, that worked for me.