1

I'm running into an error - duplicate exists - while trying to test my PushTopic creation class. This is an known issue from 4 years ago (PushTopic Test: Duplicate Name Bug?)

In the meantime, is there any workaround how to test the following code snippet?

The only fix I see is to add a method parameter and name the pushtopic dynamically (eg. by adding String pushTopicName) or something. But this doesn't seem best practice.

    //Create Pushtopic only containing account creates
    public static void startCreateTopic()
    {

        //clear existing topic
        delete [SELECT Id, Name FROM PushTopic where name = 'AccountCreatesTopic'];

        PushTopic topic = new PushTopic();
        topic.Name = 'AccountCreatesTopic'; 

The following test method runs into issues (not even inserting assert statements - just trying to get it running first) :

@isTest(SeeAllData=false)
public class PushTopic_AccountTest {

    static testMethod void testCreatePushTopicCreation(){
        PushTopic_Account.startCreateTopic();

        try {
            PushTopic t = [SELECT Id, Name FROM PushTopic WHERE name='AccountCreatesTopic'];
            // The pushtopic has to exist so it cannot return a null value -> else the test fails
        } catch (Exception e){
        }
    }

The following error occurs:

System.DmlException: Insert failed. First exception on row 0; first error: DUPLICATE_VALUE, A PushTopic with this name already exists. Please choose a different name.: []

----------- UPDATE ------------

I managed to get some of the class tested by doing the following : But now still the problems occurs - I cannot reach 100% coverage?

@TestVisible
private static void StartCreateTopic(String name){
    startCreateTopicName(name);
}

// Standard method -- These 3 lines cannot be tested.
public static void startCreateTopic(){
    startCreateTopicName('AccountCreatesTopic');
}

// Create Pushtopic only containing account creates   
public static void >startCreateTopicName(String pushTopicName)    {

  //clear existing topic      
  delete [SELECT Id, Name FROM PushTopic
                            where name =: pushTopicName];

  PushTopic topic = new PushTopic();
2
+50

Here's how I would refactor the startCreateTopic method to achieve 100% coverage:

public static void startCreateTopic(){
    String topicName = 'AccountCreatesTopic';
    if(Test.isRunningTest(){
        topicName += 'Test';
    }
    startCreateTopicName('AccountCreatesTopic');
}

Now you can safely call startCreateTopic from your test code, and every line will execute. It might seem like it's not best practice, but the platform doesn't allow you to do better so I'd argue that it is.

  • This seems indeed the most clean option to still maintain the default value but allow 100% coverage. Thanks! – Koen Certyn Nov 10 '17 at 7:14
1

Sometimes some actions you can't cover with unit tests.

For example, if you have some callouts, you can't execute callout in test execution context.

For such cases you might use Test.isRunningTest() method and determine if you are inside the Test execution context and do some fake logic inside of tests.

For example, if you need to cover the following method

public static void startCreateTopic() {
    insert new PushTopic();
}

and you struggle to execute this in test contest (since it would create duplicated record), you might omit the actual execution and get 100% coverage using Test.isRunningTest() method if you change you method to the following form:

public static void startCreateTopic() {
    if (!Test.isRunningTest()) insert new PushTopic(); // else do nothing
}

However, using of Test.isRunningTest() method is also considered bad practice but this may help as the last resort if you can't find any viable good practice solution which would give you 100% coverage.

Also recently Salesforce released a new feature called mocking tests with stub interface, I have mentioned it in my post. I haven't actually tried to create stub interface and use it with method Test.createStub, so I am not sure if that would give 100% coverage, but you may try to use this approach as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.