No Method Signature of Keyword class

I created a Keyword class in Katalon called, “OrganizationKeywords.groovy”. The class takes in the following types of parameters as shown here:

@Keyword
def createTestOrganization(
			Integer orgTypeId,
			String orgType,
			String orgNumber,
			String legalName,
			String addressLine1,
			String addressLine2,
			String cityName,
			String stateCode,
			String zipCode,
			String zipExtn,
			String vendorId,
			String adminFirstName,
			String adminLastName,
			String adminUserName,
			String adminEmail,
			String adminMobilePhoneNumber) {
//Code Stuff Here.
}

I have another class called, “AccountKeywords.groovy”, that calls on the above function in this exact fashion:

                Integer orgTypeId = 2;
		orgType = 'TEST';
		orgNumber = 'TESTORG';
		String legalName = 'TESTORG';
		String addressLine1 = 'addressLine1';
		String addressLine2 = 'addressLine2';
		String cityName = 'cityName';
		String stateCode = 'NY';
		String zipCode = '11215';
		String zipExtn = '123';
		String vendorId = '1';
		def wyoOrgIds = [];
		String adminFirstName = 'testAdminFirstName';
		String adminLastName = 'testAdminLastName';
		String adminUserName = 'testAdmin';
		String adminEmail = 'testAdmin@adminEmail.com';
		String adminMobilePhoneNumber = '111-111-1111';

		OrganizationKeywords.createTestOrganization(
				orgTypeId,
				orgType,
				orgNumber,
				legalName,
				addressLine1,
				addressLine2,
				cityName,
				stateCode,
				zipCode,
				zipExtn,
				vendorId,
				adminFirstName,
				adminLastName,
				adminUserName,
				adminEmail,
				adminMobilePhoneNumber
				);

Both “AccountKeywords.groovy” and “OrganizationKeywords.groovy” sit in the same project folder. When I run my code, I get this stack trace error:

org.codehaus.groovy.runtime.InvokerInvocationException: groovy.lang.MissingMethodException: No signature of method: static gov.dhs.fema.pivot.OrganizationKeywords.createTestOrganization() is applicable for argument types: (java.lang.Integer, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) values: [2, WYO, TESTORG, TESTORG, addressLine1, addressLine2, cityName, ...]
Possible solutions: createTestOrganization(java.lang.Integer, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	at gov.dhs.fema.pivot.AccountKeywords.invokeMethod(AccountKeywords.groovy)
	at com.kms.katalon.core.main.CustomKeywordDelegatingMetaClass.invokeStaticMethod(CustomKeywordDelegatingMetaClass.java:50)
	at WHEN - PUT-account is called.run(WHEN - PUT-account is called:70)
	at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
	at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
	at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:369)
	at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:360)
	at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:339)
	at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:331)
	at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:248)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:142)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:133)
	at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
	at TempTestCase1631041163603.run(TempTestCase1631041163603.groovy:25)

Could someone tell me what I’m doing wrong here? The method signature seems to line up. Is there an issue with how methods should be written in Katalon that I’m not getting?

I agree, it does.

Make sure these are Strings:

Nothing wrong with what I see (I might code it differently, but that’s not a criticism).

Congrats on a great report – very well put together. :clap:

BTW, you can lose the semi-colons.

@czhuang

Your code has a mistake. You need to add static modifier as follows.

@Keyword
static def createTestOrganization(
			Integer orgTypeId,
            ...

It is because your test case wants to call the createTestOrganization method as a static method of the OrganizationKeywords class:

        OrganizationKeywords.createTestOrganization(...


If you do NOT want to declare the method as static, then your test case should be

        new OrganiizationKeywords().createTestOrganiization(...

Or you may write:

        CustomKeywords.'fully.qualified.classname.OrganizationKeywords.createTestOrganization'(...

This would work in both cases where with or without static modifier to the createTestOrganization method. CustomKeywords class internally calls new fully.qualified.classname.OrganizationKeywords().createTestOrganization(..., therefore static modifier becomes unnecessary.

I also might code it differently. I feel awful to have 16 positional arguments for a method, as I am sure I will make mistakes and will find it difficult to debug.

Several alternatives could there be. Just to give you an idea…:

	@Keyword
	static def createTestOrganization(Integer orgTypeId, Map<String, String> p) {
		// Code stuff here
		println "orgType: + " + p.orgType
		println "orgNumber:" + p.orgNumber
		println "legalName: " + p.legalName
		println "addressLine1: " + p.addressLine1
		println "addressLine2: " + p.addressLine2
		println "cityName: " + p.cityName
		println "stateCode: " + p.stateCode
		println "zipCode: " + p.zipCode
		println "zipExtn: " + p.zipExtn
		println "vendorId" + p.vendorId
		println "adminFirstName: " + p.adminFirstName
		println "adminLastName: " + p.adminLastName
		println "adminUserName: " + p.adminUserName
		println "adminEmail: " + p.adminEmail
		println "adminMobilePhoneNumber:" + p.adminMobilePhoneNumber
	}

Your test case might be

    OrganizationKeyword.createTestOriganization(
        0, 
        [
            "orgType": "TEST",
            "cityName": "cityName"
        ])

When you execute the test case, it will print in the Console

2021-09-08 10:53:07.631 DEBUG testcase.czhuang                         - 1: OrganizationKeywords.createTestOrganization(999, ["orgType":"TEST", "cityName":"cityName"])
orgType: + TEST
orgNumber:null
legalName: null
addressLine1: null
addressLine2: null
cityName: cityName
stateCode: null
zipCode: null
zipExtn: null
vendorIdnull
adminFirstName: null
adminLastName: null
adminUserName: null
adminEmail: null
adminMobilePhoneNumber:null

Furthermore, you may want to give sensible default values (rather than null) to each of parameters. A quick fix could be:

	@Keyword
	static def createTestOrganization(Integer orgTypeId, Map<String, String> p) {
        Map<String, String> defaults = [
		        "orgType": "any default",
                "orgNumber": "any default",
                "legalName": "any default",
                ...
                ])
        defaults.putAll(p)
        // Code stuff here

But I would suggest a more sophisticated approach:

  1. you would create a class (e.g, “Params”) instead of Map<String, String> p
  2. you want to design the “Params” class so that it can provide appropriate defaults. You would need to study Joshua Bloch’s “Builder pattern”. See:
1 Like