Menu

Step 3: A word about values

ponchy

Step 3: A word about values

ScenarLang gives you access to the following kind of objects :

  • basic values (boolean, numeric, string, null)
  • arrays
  • subclasses of java.lang.Collection
  • map (hashmap)
  • mock objects
  • resources / files
  • a reference
  • POJOs
  • any object parseable with a custom parser
  • any object you can instanciate

There is also a shortcut notation for objects that can be unmarsalled with jaxb

You can use these values/objects to :

  • assign a value to a variable.
  • be a parameter in a function.
  • be a function call result (see Behavior Configuration).
  • set a new value to an other object's field.
  • set a new value to a static field

Basic values

Basic values are pretty much the same as there of Java :

::java

// A whole number writes 
$WHOLE = 4;
// A decimal number writes
$DECIMAL = 4.5;

// A string
$STRING = "Some text";

// a boolean
$BOOLEAN = true;

$NULL = null;

Note : As a general rule, if you want to enforce a given type you need to add a type constraint which means you can specify the type after the keyword as.

::java

// here we make sure it is a Long
$SOME_LONG = 4 as "java.lang.Long";

Arrays

To declare an array you should give a list of values separated by commas and square it with square-brackets.

::bash

$THIS_IS_AN_ARRAY = [ "one", "two", "three" ];

Collections

Collections are basically arrays with an extra type constraint on it : which means you declare an array list as such.

::bash

$LIST = [ "one", "two", "three" ] as "java.util.ArrayList";

Maps

Maps are a particuliar case of collection and therefore require a little extra syntax. Instead of just specifying objects, you need to specify associations. You can do so by putting a => sign between the key and the value.

::bash

// Note : using this syntax, the scenarlang runtime is able to infer that the type is Map.
// Note2: the key does not necessarily need to be a string, it can be any kind of value.
$MY_MAP = [ "key" => 43, "other_key" => mock "Person" ];

Mock objects

Instanciating a mock object is done via the mock keyword followed by a type name (or alias).

Limitation: you can only create a mock object for types that are not declared final.

::bash

$MOCK = mock "some.Class";

Resource Files

If ever in one of your test setups you need to gain access to one of your test resources, you can easily get a File reference to it using the keyword resource.

::java

$SOME_FILE = resource "/some/file/in/a/folder/file.txt";

References

There exists several kind of references :

  • Variables
  • External references
  • Fields of any object
  • Fields of any class
  • Function calls

Variables

We already talked about variables previously but if you skipped the beginning, here is a little refresh. Variables are declared and referenced in the same way : you simply prefix the variable name with a $ (dollar).

Variables can:

  • be reassigned during the script (but that's IMHO no good idea).
  • hold any kind of data (simple value, object, null, ...)

Example

::bash
$THE_ANSWER = 42;

External references

You can access the 'context' (the test class or alternatively a field from the test class that is annotated with @Context) fields directly via their name.

Example
Java test class
::java
public class MyTestClass {
    private TestedType tested;
    // ... 
}
Scn script
::java
// tested is actually the field coming from the previously defined test class
// Here we inject a value into the 'someService' field
// of the object 'tested' declared in our context.
tested.someService = mock "the.service.to.be.Mocked";

Field references

Accessing a field reference is done in the same way as in Java (and I already showed many examples that do so) : you simply specify the parent object name followed by a dot and the name of the child property.

Here is what it looks like :

::java

// sets a value in the 'child' field of the 'parent' object
parent.child = 42;

// it works ie for a variable too
$PARENT.child = 42;

Static field references

You can access any static member of a class with the following syntax :
static "className" -> fieldname

::java

static "some.Class" -> instance = null;

$A = static "some.Class" -> doSomething();
~~~~~~~~~

### Function calls ###
Function calls use the same syntax as Java.

~~~~~~
::bash
$SOMETING = object.sub.something();
~~~~~~

## POJOS ##
ScenarLang let's you instanciate any POJO in a pretty expressive using a syntax close to that of JSON. 

### Using the no-arg constructor ###
If you can afford to use the no-argument constructor (be it private), then you can use the simplified syntax which is: _**{ fieldname : fieldValue }**_ where fieldname : fieldValue can repeat at will (but need to be separated by a comma).

~~~~~~
::java

// This instanciate an object of the type "the.pojo.Type"
$A_POJO = {
    someLong: 4,
    someText: "text",
    someFlag: true,
    someArray: [ 3, 4, 5 ],
    // Here you don't need to specify a type, 
    // the scenarlang runtime will infer it
    // for you.
    someNestedObject: {
        someChildProp: "some child prop"
    }
} as "the.pojo.Type";
~~~~~~

### Using a specific constructor ###
If you need to use a specific constructor or there is no default constructor, then you can use the longer syntax : 

~~~~~~
::java

// This uses the 2 argument constructor defined in the class Person.
$A_PERSON = new ("the_name", "the_first_name") -> {
    // If you want you can specify some fields with 
    // field : fieldValue
} as "Person";
~~~~~~

#### Notes : ####
* You are always setting **FIELDS**
* If you want to declare an object, it must start with { and finish with } (like in json).
* If you want to declare an array or collection, it must start with \[ and finish with  \] (like in json).
* If you want to assign a type to a value, you use an 'as' clause : {} as "your.object.InnovativeType";
* If you set no type to a {} construct, you get a Map<String, Object>
* Types are inferred whenever possible so that you don't need to specify it for each and every field or value.
* You can instanciate a mock with the *mock "some.Type";* instruction.
* Properties in an object declaration or values in a collection are separated by commas 
* When instanciating a pojo, the constructor part is optional as well as the type constraint but the **{}** are the minimal tokens required to instanciate an object.

## Interaction with JAXB ##
If you have an xml document that you could normally unmarshal with JaxWS/JaxB, then you don't need to rewrite your whole object using the scenar notation (that would be a waste of time). What you can do is simply use the follwing syntax :

~~~~~~~~~~~~~~
// resource file starts with a slash and will be looked up at the root of 
// your jar (test-classes folder for maven users)
$MXL_REQUEST = jaxb from resource "/some/resource/file.xml" as "some_type";

// As usual, you can alter the content of the object loaded 
// with jaxb using ScenarLang 'usual' syntax.
$XML_REQUEST.sub_field.sub_sub_field = "Hello world !";
~~~~~~~~~~~~~~

## Objects with a custom parser ##
This example was already detailed in the Step 1 in the paragraph about conversion configuration. You'll typically use a custom conversion when you want to instanciate a Date or an Enum. The following example shows an use case with an enum.

#### The java code ####
~~~~~~~
::java

public enum Guy { 
    ME, YOU, THEM;

    /*
     * It is IMHO a bad idea to place the annotation
     * @ConversionMethod directly here because you normally
     * don't want to embed ScenarLang direcly in your production
     * binary.
     */         
    public static Guy fromString(String name){
        if("ME".equals(name)) return ME;
        if("YOU".equals(name)) return YOU;
        if("THEM".equals(name)) return THEM;
        return null;
    }
}

public class GuyParser {
    @ConversionMethod
    public static Object guyFromString(String text){
        return Guy.fromString(text);
    }
}
~~~~~~~~~

#### The scn ####

::bash

parse "Guy" with "GuyParser";

$them = "THEM" as "Guy";
~~~~~~~~

STEP 2: Your 1st scenario
STEP 4: Matchers (TODO)


MongoDB Logo MongoDB