Script binding does not work before calling Script.run() - variables

I've the following test code to figure out how variable binding works. So this is what I want to import/include;
# importee.groovy
import groovy.transform.Field
#Field top = 60
number = 44 // binding variable
int ratio = 4.5
return this
which I call it from;
# importer.groovy (version1)
import groovy.lang.GroovyClassLoader
def gcl = new GroovyClassLoader()
def clazz = gcl.parseClass(new File("importee.groovy")) )
assert clazz.name == 'importee'
def script = clazz.newInstance()
//script.run()
println("binding variable:
${script.getBinding().getVariable("number")}")
So, if I don't run the script, my test code throws "MissingPropertyException" on the last print statement. This is not happenning if I call def script = evaluate(new File("importee.groovy")) instead of using GroovyClassLoader like this;
# importer.groovy (version2)
def script = evaluate(new File("importee.groovy"))
println("binding/global variable: ${script.number}")
Since both methods return a Script instance, I got a little bit confused on why I have to call the run() method in the first case. Can someone explain where I fail to understand please?
Thanks

run groovyconsole (distributed with groovy)
type a simple script:
number=44
return this
select menu Script -> Inspect Ast
and in the new window Groovy AST Browser select phase = Conversion
you will see your groovy script but converted to a Script class like this:
public class script1548245785832 extends groovy.lang.Script {
public script1548245785832() {
}
public java.lang.Object run() {
number = 44
return this
}
}
this is the actual code generated for your script.
as you can see the constructor is empty, so no information about number property after you call newInstance()
but after you call run() you actually run your script.
your script could be a class like this:
class Importee {
int number=44
public Object run(){
println number
}
}
in this case it will be enough to create instance of class without calling run() method and get the value of number variable...
def clazz = gcl.parseClass( new File("Importee.groovy")) )
def script = clazz.newInstance()
println("the variable: ${script.number}")

Related

How to unit test azure function using Xunit and Moq

I am very new to unit tests and recently started learning it from various online resources.
But still it confuses me when I need to implement it in my code.
For the given image which I have attached here, could anyone of you suggest me how should I start or where to start?
This is Azure function which I will be creating unit test for, framework/library I would prefer is Xunit and moq.
As mentioned in a comment, a good place to start when unit testing is looking at your code and identifying the different "paths" it can take and what the result of that path will be.
if (inventoryRequest != null)
{
// path 1
await _inventoryService.ProcessRequest(inventoryRequest);
_logger.LogInformation("HBSI Inventory Queue trigger function processed.");
}
else
{
// path 2
_logger.LogInformation("Unable to process HBSI Rate plan Queue.");
}
In your code, because of your if statement, there are 2 possible paths which will end in 2 different results = 2 unit tests.
Now you can start creating your unit tests but first you need to find out what you need to set up to be able to trigger your code.
private readonly ILogger _logger;
private readonly IInventoryService _inventoryService;
public InventoryServiceBusFunction(ILogger logger, IInventoryService inventoryService)
{
_logger = logger;
_inventoryService = inventoryService;
}
You have some dependencies being passed into your constructor with interfaces - great, this means we can mock them. We want to mock dependencies in unit tests because we want to control their behaviour for the tests. Also, mocking the dependencies negates any "real" behaviour the dependency might be performing i.e. database operations, API calls etc.
Using Moq we can mock the objects like so:
public class InventoryServiceBusFunctionTests
{
private readonly Mock<ILogger> _mockLogger = new Mock<ILogger>();
private readonly Mock<IInventoryService> _mockInventoryService = new Mock<IInventoryService>();
...
We will use these mocks later to make verifications on behaviour we expect to happen.
Next, we need to create an instance of the actual class we want to test.
// using a constructor in the test class will run this code before each test
public InventoryServiceBusFunctionTests()
{
// pass the mocked objects to initialize class
_inventoryServiceBusFunction = new InventoryServiceBusFunction(_mockLogger.Object, _mockInventoryService.Object);
}
Now that we have an instance of the InventoryServiceBusFunction class, we can use any of the public properties/methods in our tests.
[Fact]
public async Task GivenInventoryRequest_WhenFunctionRuns_ThenInventoryServiceProcessesRequest()
{
Now, remembering the paths from earlier, we can start to create the test cases. We can take the first path and create a [Fact] for it. You want to give your test case a meaningful name. I usually use the style of Given_When_Then to describe what is expected to happen.
Next, I usually add 3 comment sections to my test case:
// arrange
// act
// assert
This allows me to clearly see which parts of the test are doing what.
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
Next, I would fill in the \\ act section because this will tell me (via Intellisense) what I need to arrange. e.g. above, when hovering my mouse over the Run method, I can see that I need to pass an instance of InventoryRequest.
// arrange
var inventoryRequest = new InventoryRequest
{
Name = "abc123",
Quantity = 2,
Tags = new List<string>
{
"foo"
}
};
In the \\ arrange section, initialize an instance of the InventoryRequest class and set the properties. This can be any data as we aren't really interested in the data itself but more what happens when the code runs.
if (inventoryRequest != null)
{
// path 1
await _inventoryService.ProcessRequest(inventoryRequest);
_logger.LogInformation("HBSI Inventory Queue trigger function processed.");
}
Lastly, the \\ assert section. Here, we want to make assertions on what we expect to happen given the set up of the test. So given the InventoryRequest is not null, we expect the if to evaluate to true and we expect the _inventoryService.ProcessRequest(inventoryRequest) method to be executed.
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.Is<InventoryRequest>(ir => ir.Name == inventoryRequest.Name
&& ir.Quantity == inventoryRequest.Quantity
&& ir.Tags.Contains(inventoryRequest.Tags[0]))));
In Moq, we can use the .Verify() method on the mock object to assert that the method was called. We can use the It.Is<T> syntax to make assertions on the data that is passed to the method.
Here is the full test case for path 1:
[Fact]
public async Task GivenInventoryRequest_WhenFunctionRuns_ThenInventoryServiceProcessesRequest()
{
// arrange
var inventoryRequest = new InventoryRequest
{
Name = "abc123",
Quantity = 2,
Tags = new List<string>
{
"foo"
}
};
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.Is<InventoryRequest>(ir => ir.Name == inventoryRequest.Name
&& ir.Quantity == inventoryRequest.Quantity
&& ir.Tags.Contains(inventoryRequest.Tags[0]))));
}
Then for path 2, you are setting up the test so that the else condition is executed.
[Fact]
public async Task GivenInventoryRequestIsNull_WhenFunctionRuns_ThenInventoryServiceDoesNotProcessRequest()
{
// arrange
InventoryRequest inventoryRequest = null;
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.IsAny<InventoryRequest>()), Times.Never);
}
Note - in the \\ assert here, I am asserting that the await _inventoryService.ProcessRequest(inventoryRequest) method is never called. This is because you want the test to fail in this scenario as the method should only be executed in the if condition. You may also choose to verify that the logger method is called with the correct message.

How to create GlobalVariable during runtime in katalon using scriptmode?

I m new to katalon studio tool and trying to add GlobalVariable during runtime by taking "variable Name" & "Value" as inputs.
I m come across block of code which will help me in this. But i m facing difficulties in understanding this piece of code,because it uses metaprogramming in Groovy.
void addGlobalVariable(String name, def value) {
MetaClass mc = script.evaluate("internal.GlobalVariable").metaClass
String getterName = "get" + name.capitalize()
mc.static."$getterName" = { -> return value }
//mc.static."$name" = value
}
i am getting "InvocationTargetException" when i m running it.and also katalon IDE doesn't recognize these keywords "script","evaluate" & static.
you looking for clarity on this block code or you can suggest me any other possible solution.
After my test, the following code can achieve the effect:
1.Define a Keyword:
import com.kms.katalon.core.annotation.Keyword
package com.becelever.util
public class GlobalVariableUtils {
#Keyword
static void addGlobalVariable(String name, def value) {
GroovyShell shell1 = new GroovyShell()
MetaClass mc = shell1.evaluate("internal.GlobalVariable").metaClass
String getterName = "get" + name.capitalize()
mc.'static'."$getterName" = { -> return value }
mc.'static'."$name" = value
}
}
2.then invoke it and verify:
CustomKeywords.'com.becelever.util.GlobalVariableUtils.addGlobalVariable'('localURL', 'katalon.com')
println(GlobalVariable.localURL)
println(GlobalVariable.getLocalURL())
Note: I found that the first letter of the variable could not be capitalized. For example, if I changed it to "LocalURL", it failed.
Auto-import the required libraries. You do this by pressing Ctrl+Shift+O.

How to invoke method with sql request in separate class from Groovy script in SOAP UI?

Friends, hello.
I'am trying to use elements of object oriented approach in SOAP UI groovy scripting.
I read manual about "How to write a reusable script" here http://forum.loadui.org/viewtopic.php?f=1&t=15744
and I am trying to write a separate class with method which get data from database and set up address properties (Address).
My problem is that i receive the error message
groovy.lang.MissingPropertyException: No such property: sql1 for class
Utils error at line: 138
when run "main" Groovy script.
"Main" Groovy Script looks like:
// get a reference to the library TestSuite
library = testRunner.testCase.testSuite.project.testSuites["Library"]
// find the module within the library
module = library.testCases["module-name"].testSteps["Utils"]
// initialise the library; which places an instance of Example in the context
module.run(testRunner, context)
// get the instance of example from the context.
def utils = context.utils
// run the method, with parameter
log.info "utils.setAddress() = " + utils.setAddress("LivingPlace");
setAddress method is determined in class Utils which is looked like:
import groovy.sql.Sql;
class Utils
{
def log
def context
def testRunner
// Class constructor with same case as Class name
def Utils(logIn, contextIn, testRunnerIn)
{
this.log = logIn
this.context = contextIn
this.testRunner = testRunnerIn
}
def setAddress (addressType)
{
log.info testRunner;
log.info context;
log.info "Call the DB" ;
com.eviware.soapui.support.GroovyUtils.registerJdbcDriver("com.microsoft.sqlserver.jdbc.SQLServerDriver");
sql1 = Sql.newInstance("jdbc:sqlserver://SRV1:1433; databaseName=DB;", "user", "123", "com.microsoft.sqlserver.jdbc.SQLServerDriver");
sql1.eachRow('select top 1 '+
'Country '+
'from Address')
{ row ->
testRunner.testCase.testSteps['Address'].setPropertyValue("'country", "$row.Country");
}
return addressType //just for test
}
}
context.setProperty ("utils", new Utils(log, context, testRunner) )
log.info "Library Context:"+context;
If i delete everything related with sql it works fine. How to invoke the setAddress method without error described earlier and set Adress properties?

How to mock the 'new' operator

I'm testing some groovy code that uses a java library and I want to mock out the library calls because they use the network. So the code under test looks something like:
def verifyInformation(String information) {
def request = new OusideLibraryRequest().compose(information)
new OutsideLibraryClient().verify(request)
}
I tried using MockFor and StubFor but I get errors such as:
No signature of method: com.myproject.OutsideLibraryTests.MockFor() is applicable for argument types: (java.lang.Class) values: [class com.otherCompany.OusideLibraryRequest]
I'm using Grails 2.0.3.
I've just found that we can always overwrite a constructor via MetaClass, as Grails 2 will be reset MetaClass modification at the end of each test.
This trick is better than Groovy's MockFor. AFAIK, Groovy's MockFor does not allow us to mock JDK's classes, java.io.File, for example. However in the below example, you cannot use File file = new File("aaa") as the real object type is a Map, not a File. The example is a Spock specification.
def "test mock"() {
setup:
def fileControl = mockFor(File)
File.metaClass.constructor = { String name -> [name: name] }
def file = new File("aaaa")
expect:
file.name == "aaaa"
}
The second, optional parameter to MockFor's constructor is interceptConstruction. If you set this to true, you can mock the constructor. Example:
import groovy.mock.interceptor.MockFor
class SomeClass {
def prop
SomeClass() {
prop = "real"
}
}
def mock = new MockFor(SomeClass, true)
mock.demand.with {
SomeClass() { new Expando([prop: "fake"]) }
}
mock.use {
def mockedSomeClass = new SomeClass()
assert mockedSomeClass.prop == "fake"
}
Note, however, you can only mock out groovy objects like this. If you're stuck with a Java library, you can pull the construction of the Java object into a factory method and mock that.

Seems Like Groovy acts Differently on these two scenarios?

I have two domain classes like this, first namely Manager :
package com.mnm
class Manager {
String name;
static hasMany = [ project : Project, tasks : Tasks ]
static constraints = {
}
}
And second one namely, Project:
package com.mnm
class Project {
String projectTitle
String projectDescription
String description
static belongsTo = [ managers: Manager ]
static hasMany = [ tasks : Tasks ]
static constraints = {
}
}
And I wrote Integration test like this (to find the name of the projects via using Manager) :
void testCountProject() {
def manager = new Manager(name:'Anto').save()
manager.addToProject(new Project(projectTitle:'Grails'))
manager.addToProject(new Project(projectTitle:'Griffon'))
def noOfProjects = Manager.get(manager.id)
def found = noOfProjects.project.collect { it.projectTitle }
assertEquals(['Grails','Griffon'], found.sort())
}
Well there is no error in it and the test passes! But when I add more stuffs into to the same test like (now I'm trying the reverse, finding the Manager name via using Project) :
void testCountProject() {
def manager = new Manager(name:'Anto').save()
def project1 = new Project(projectTitle:'Grails').save()
manager.addToProject(project1)
manager.addToProject(new Project(projectTitle:'Griffon'))
def noOfProjects = Manager.get(manager.id)
def found = noOfProjects.project.collect { it.projectTitle }
assertEquals(['Grails','Griffon'], found.sort())
def noOfManager = Project.get(project.id)
def foundManager = noOfManager.managers.collect { it.name }
assertEquals(['Anto'],foundManager)
}
Now I get the error like this :
No signature of method: com.mnm.Manager.addToProject() is applicable for argument types: (null) values: [null] Possible solutions: addToProject(java.lang.Object), getProject()
Where I went wrong?
Thanks in advance.
You have the same problem in both cases, but the first isn't a proper test so it seems to work. The issue is that all properties are not-null by default, so your Project instances fail validation when you only set projectTitle.
In the first test you don't re-load the manager instance, you're still using the one in-memory because get() uses the Hibernate session as a 1st-level cache. If you flush and clear the session to force it to go to the database it will fail:
class MyTest extends GroovyTestCase {
def sessionFactory
void testCountProject() {
def manager = new Manager(name:'Anto')
manager.addToProject(new Project(projectTitle:'Grails'))
manager.addToProject(new Project(projectTitle:'Griffon'))
manager.save(flush: true)
sessionFactory.currentSession.clear()
def noOfProjects = Manager.get(manager.id)
def found = noOfProjects.project.collect { it.projectTitle }
assertEquals(['Grails','Griffon'], found.sort())
}
}
The second one fails because you call save() on the Project instance and it returns null when validation fails. You don't need to save Project instances because they will be transitively saved when the containing Manager gets saved - the more standard pattern is the one you use in the first test.
You have a few options. One is to fix the validation errors :) Another is to check for validation errors. This requires a separate save() call so you have access to the not-null instance:
def project1 = new Project(projectTitle:'Grails')
project1.save()
if (project1.hasErrors()) {
// handle errors
}
else {
manager.addToProject(project1)
}
The third is failOnError which will throw an exception when validation fails:
def project1 = new Project(projectTitle:'Grails').save(failOnError: true)
manager.addToProject(project1)