Instantiate Xbase XExpressions programmatically - abstract-syntax-tree

I'm working on an Xtext project that uses parts of the Xbase grammar. In my code I'm analysing the DSL program in order to generate some Java code. It's easy to turn an existing XExpression into Java code using XbaseCompiler but that's not what I need. Instead, I need to generate a different program.
Currently I'm simply generating Java code (i.e. constructing a String). What I'd like to do is constructing a new XExpression, maybe even using parts of the original one, and then compile it to Java.
The different XExpressions have zero-args constructors, so I tried instantiating one and even set some of the properties. However the compiler crashed and I can't work out which properties it is missing.

I would prefer to generate the expression as String and then use the Xtext parser to do the heavy lifting for you, i.e. let it parse the String and create the corresponding XExpression objects for you. How you do that properly depends on the context you're in (OSGI or standalone).
Here is a standalone example (can be run from a simple main method) for the "Scripting Language" from the Xtext documentation:
public class StandaloneParser {
#Inject
private IParser parser;
public StandaloneParser() {
Injector injector = new ScriptingStandaloneSetup().createInjectorAndDoEMFRegistration();
injector.injectMembers(this);
}
public EObject parse(String input) {
IParseResult result = parser.parse(new StringReader(input));
if (result.hasSyntaxErrors()) {
throw new RuntimeException("Syntax errors");
}
return result.getRootASTElement();
}
}
Example for a caller:
public class Main {
public static void main(String[] args) {
StandaloneParser parser = new StandaloneParser();
EObject result = parser.parse("val answer = 7 * 6;");
System.out.println(result);
}
}
If you try to create such an expression programatically you'll have a hard time. It could look like this (Xtend code):
val factory = XbaseFactory.eINSTANCE
val expression = factory.createXVariableDeclaration => [
name = "answer"
right = factory.createXBinaryOperation => [
leftOperand = factory.createXNumberLiteral => [
value = "7"
]
feature = // TODO retrieve the JvmOperation: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_multiply(int,int)
rightOperand = factory.createXNumberLiteral => [
value = "6"
]
]
]

Related

Java 8: convert lambda to a Method instance with closure included

(This is difficult to search because results are all about "method reference")
I want to get a Method instance for a lambda expression for use with a legacy reflection-based API. The clousure should be included, so calling thatMethod.invoke(null, ...) should have the same effect as calling the lambda.
I have looked at MethodHandles.Lookup, but it only seems to be relevant for the reverse transform. But I guess the bind method may help to include the clousure?
Edit:
Say I have am lambda experssion:
Function<String, String> sayHello = name -> "Hello, " + name;
and I have a legacy framework (SpEL) that has an API like
registerFunction(String name, Method method)
which will call the given Method with no this argument (i.e. Method assumed to be static). So I'll need to get a special Method instance that includes the lambda logic + the clousure data.
In case you don't find an elegant way, here is the ugly way (Ideone). Usual warning when reflection is involved: may break in future releases etc.
public static void main(String[] args) throws Exception {
Function<String, String> sayHello = name -> "Hello, " + name;
Method m = getMethodFromLambda(sayHello);
registerFunction("World", m);
}
static void registerFunction(String name, Method method) throws Exception {
String result = (String) method.invoke(null, name);
System.out.println("result = " + result);
}
private static Method getMethodFromLambda(Function<String, String> lambda) throws Exception {
Constructor<?> c = Method.class.getDeclaredConstructors()[0];
c.setAccessible(true);
Method m = (Method) c.newInstance(null, null, null, null, null, 0, 0, null, null, null, null);
m.setAccessible(true); //sets override field to true
//m.methodAccessor = new LambdaAccessor(...)
Field ma = Method.class.getDeclaredField("methodAccessor");
ma.setAccessible(true);
ma.set(m, new LambdaAccessor(array -> lambda.apply((String) array[0])));
return m;
}
static class LambdaAccessor implements MethodAccessor {
private final Function<Object[], Object> lambda;
public LambdaAccessor(Function<Object[], Object> lambda) {
this.lambda = lambda;
}
#Override public Object invoke(Object o, Object[] os) {
return lambda.apply(os);
}
}
Well, lambda expressions are desugared into methods during compilation and as long as they don’t capture this (don’t access non-static members), these methods will be static. The tricky part is to get to these methods as there is no inspectable connection between the functional interface instance and its target method.
To illustrate this, here the simplest case:
public class LambdaToMethod {
public static void legacyCaller(Object arg, Method m) {
System.out.println("calling Method \""+m.getName()+"\" reflectively");
try {
m.invoke(null, arg);
} catch(ReflectiveOperationException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) throws URISyntaxException
{
Consumer<String> consumer=s -> System.out.println("lambda called with "+s);
for(Method m: LambdaToMethod.class.getDeclaredMethods())
if(m.isSynthetic() && m.getName().contains("lambda")) {
legacyCaller("a string", m);
break;
}
}
}
This works smoothly as there is only one lambda expression and hence, one candidate method. The name of that method is compiler specific and may contain some serial numbers or hash codes, etc.
On kludge is to make the lambda expression serializable and inspect its serialized form:
static Method lambdaToMethod(Serializable lambda) {
for(Class<?> cl=lambda.getClass(); cl!=null; cl=cl.getSuperclass()) try {
Method m=cl.getDeclaredMethod("writeReplace");
m.setAccessible(true);
try {
SerializedLambda sl=(SerializedLambda)m.invoke(lambda);
return LambdaToMethod.class.getDeclaredMethod(sl.getImplMethodName(),
MethodType.fromMethodDescriptorString(sl.getImplMethodSignature(),
LambdaToMethod.class.getClassLoader()).parameterArray());
} catch(ReflectiveOperationException ex) {
throw new RuntimeException(ex);
}
} catch(NoSuchMethodException ex){}
throw new AssertionError();
}
public static void main(String[] args)
{
legacyCaller("a string", lambdaToMethod((Consumer<String>&Serializable)
s -> System.out.println("first lambda called with "+s)));
legacyCaller("a string", lambdaToMethod((Consumer<String>&Serializable)
s -> System.out.println("second lambda called with "+s)));
}
This works, however, serializable lambdas come at a high price.
The simplest solution would be to add an annotation to a parameter of the lambda expression to be found when iterating over the methods, however, currently, javac doesn’t store the annotation properly, see also this question about this topic.
But you may also consider just creating ordinary static methods holding the code instead of a lambda expression. Getting a Method object for a method is straight-forward and you still can create a functional interface instance out of them using method references…
Since the question mentions SpEL specifically (and I found the question when also working with SpEL), an alternative way to add a custom function to the evaluation context without using Method references is to add a custom MethodResolver (javadoc, GitHub) to the StandardEvaluationContext. A benefit of this approach is that one can add both static and non-static methods to the evaluation context using it, where only static methods could be added using the registerFunction approach.
The code to add a custom MethodResolver to the StandardEvaluationContext is fairly straightforward. Below is an executable example showing how to do so:
public static void main(String[] args) throws Exception {
Function<String, String> sayHello = name -> "Hello, " + name;
// The evaluation context must have a root object, which can be set in the StandardEvaluationContext
// constructor or in the getValue method of the Expression class. Without a root object, the custom
// MethodResolver will not be called to resolve the function.
Object rootObject = new Object();
StandardEvaluationContext standardEvaluationContext = new StandardEvaluationContext(rootObject);
// Add the custom MethodResolver to the evaluation context that will return a MethodExecutor that
// Spring can use to execute the sayHello function when an expression contains "sayHello('<any string>')".
standardEvaluationContext.addMethodResolver((context, targetObject, methodName, argumentTypes) -> {
MethodExecutor methodExecutor = null;
if (methodName.equals("sayHello")
&& argumentTypes.size() == 1
&& String.class.isAssignableFrom(argumentTypes.get(0).getObjectType())
) {
methodExecutor = (innerContext, target, arguments) -> {
final String name = arguments[0].toString();
return new TypedValue(sayHello.apply(name));
};
}
return methodExecutor;
});
// Create an expression parser, parser the expression, and get the evaluated value of the expression.
SpelExpressionParser expressionParser = new SpelExpressionParser();
Expression expression = expressionParser.parseExpression("sayHello('World!')");
String expressionValue = expression.getValue(standardEvaluationContext, String.class);
// Output the expression value, "Hello, World!", to the console.
System.out.println(expressionValue);
}
The value of the expression that was output to the console by executing the above code was:
Hello, World!
Note that when using a MethodResolver to add a function to the evaluation conext, the function should not be prefixed with a # in the expression string. This is a major difference between using the MethodResolver and using the registerFunction method to add a function to the evaluation context.
sayHello('World!') // will work!
#sayHello('World!') // will not work!
Keep this in mind if you are considering migrating an existing solution from using the registerFunction approach to using the MethodResolver approach.

How to setup Moq to execute some methods of a Moq

I have a test where I pass in an object like so:
var repo = new ActualRepo();
var sut = new Sut(repo);
In my test, Repo has one method that I need to actually execute, whilst another method I want to mock out and not execute.
So for example, take this pseudocode:
var repo = new Mock<IRepo>();
repo.Setup(m => m.MethodIWantToCall()).WillBeExecuted();
repo.Setup(m => m.MethodIWantToMock()).Returns(false);
Using Moq, is this possible and how can it be done?
EDIT:
I've used TypeMock in the past and you can do something like.
Isolator.When(() => repo.MethodToIgnore()).WillBeIgnored();
Isolator.When(() => repo.MethodToActuallyRun()).WillBeExecuted();
Not too sure from the question if this is useful but it is possible to partially mock an object if the method that you want to mock is virtual.
public class Foo {
public string GetLive() {
return "Hello";
}
public virtual string GetMock() {
return "Hello";
}
}
public class Snafu {
private Foo _foo;
public Snafu(Foo foo) {
_foo = foo;
}
public string GetMessage() {
return string.Format("{0} {1}", _foo.GetLive(), _foo.GetMock());
}
}
[TestMethod]
public void NotMocked() {
var snafu = new Snafu(new Foo());
Assert.AreEqual("Hello Hello", snafu.GetMessage());
}
[TestMethod]
public void Mocked() {
var mockFoo = new Mock<Foo>();
mockFoo.Setup(mk => mk.GetMock()).Returns("World");
var snafu = new Snafu(mockFoo.Object);
Assert.AreEqual("Hello World", snafu.GetMessage());
}
You can't do this with Moq if you use the same object unless one of the method is virtual and you are basing your mock on a type rather than an interface.
That's because when you are passing a mock object based on an interface, you aren't passing a real object so it does not have access to the real methods of the object.
You are passing a dynamic proxy which will respond to methods it has been setup to respond to.
I believe TypeMock rewrites the assemblies at runtime to achieve this, something Moq definitively doesn't do.
If you want to achieve similar results with Moq:
You could mock both methods
You would have to extract both methods to different dependencies so as to mock one dependency and not the other.
You could have the method you need mocked be virtual, which would be the solution I would prefer.
EDIT : I edited my answer for correctness after reading AlanT's answer.

How do I assert a method was called on this mocked dependency with moq and mspec?

I was testing a model repository to see if it calls the message bus. I am not sure if this is a good test at all but here is my thinking: I would normally put the bus.send into the controller (this is an MVC web app) but since I don't want to test my controllers specifically for logic, I moved this into the repository. Controllers are simple in my case. Repository uses the bus and the model database to build the view models.
Anyways, point of this problem is the moq test I am running. I mocked the bus and wanted to verify that it is called from the repository.
The test looks like this:
public class when_creating_new_clinic
{
Establish context = () =>
{
clinicID = Guid.NewGuid();
model = new ClinicModel
{
ClinicID = clinicID,
Alias = "alias",
Title = "title"
// stuff omitted
};
newClinicData = new NewClinicData
{
ClinicID = clinicID,
Alias = "alias",
Title = "title"
// stuff omitted
};
cmd = new CreateClinicCmd(newClinicData);
bus = new Mock<IMessageBusAgent>();
repository = new ClinicModelRepository(bus.Object);
bus.Setup(b => b.Send(cmd));
};
Because it = () => repository.Create(model);
It should_send_create_clinic_command_to_bus = () =>
{
bus.Verify(b => b.Send(cmd), Times.Exactly(1));
};
static ClinicModelRepository repository;
static ClinicModel model;
static Mock<IMessageBusAgent> bus;
static NewClinicData newClinicData;
static Guid clinicID;
static CreateClinicCmd cmd;
}
The gist of the repository is this:
public class ClinicModelRepository : IClinicModelRepository
{
private readonly IMessageBusAgent m_bus;
public ClinicModelRepository(IMessageBusAgent bus)
: this()
{
m_bus = bus;
}
public void Create(ClinicModel clinicModel)
{
// stuff omitted (data is mapped from clinicModel)
m_bus.Send(new CreateClinicCmd(data));
}
}
The IMessageBusAgent is declared as:
public interface IMessageBusAgent : IDomainCommandSender, IDomainEventPublisher, IUnitOfWork
{
}
The result of the test looks like this:
when creating new clinic
» should send create clinic command to bus (FAIL)
Test 'should send create clinic command to bus' failed:
Moq.MockException:
Expected invocation on the mock exactly 1 times, but was 0 times: b => b.Send(when_creating_new_clinic.cmd)
Configured setups:
b => b.Send<CreateClinicCmd>(when_creating_new_clinic.cmd), Times.Never
Performed invocations:
IDomainCommandSender.Send(ArReg.Commands.CreateClinicCmd)
IUnitOfWork.Commit()
at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable`1 setups, IEnumerable`1 actualCalls, Expression expression, Times times, Int32 callCount)
at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times)
at Moq.Mock.Verify[T](Mock mock, Expression`1 expression, Times times, String failMessage)
at Moq.Mock`1.Verify(Expression`1 expression, Times times)
Repositories\when_creating_new_clinic.cs(51,0): at ArReg.Tests.Specs.Repositories.when_creating_new_clinic.<.ctor>b__4()
at Machine.Specifications.Model.Specification.InvokeSpecificationField()
at Machine.Specifications.Model.Specification.Verify()
0 passed, 1 failed, 0 skipped, took 3.58 seconds (Machine.Specifications 0.4.24-f7fb6b5).
The Send() command is declared in the IDomainCommandSender so how do I need to setup the test so that I can verify the correct call?
Thanks
Your setup of the bus-moq has a little mistake. It should be like this:
bus.Setup(b => b.Send(It.IsAny<CreateClinicCmd>()));
Reason: You wrote your setup with an instance of CreateClinicCmd created two code lines above. In your class under test ClinicModelRepository you create another instance of that class and call your bus mock. This call doesn't match the call you wrote in your setup.

flexunit: Parametrized tests

I am trying to run a parametrized tests... Was trying to implement it like it explained here:
http://docs.flexunit.org/index.php?title=Parameterized_Test_Styles
Here is what my test case looking
import org.flexunit.runners.Parameterized;
[RunWith("org.flexunit.runners.Parameterized")]
public class ArrayBasedStackTests
{
[Paremeters]
public static var stackProvider:Array = [new ArrayBasedStack(), new LinkedListBasedStack()] ;
private var _stack:IStack;
public function ArrayBasedStackTests(param:IStack)
{
_stack = param;
}
[Before]
public function setUp():void
{
}
[After]
public function tearDown():void
{
}
[Test ( description = "Checks isEmpty method of the stack. For empty stack", dataProvider="stackProvider" )]
public function isEmptyStackPositiveTest():void
{
var stack:IStack = _stack;
assertEquals( true, stack.isEmpty() );
}
But this code throws following initializing Error:
Error: Custom runner class org.flexunit.runners.Parameterized should
be linked into project and implement IRunner. Further it needs to have
a constructor which either just accepts the class, or the class and a
builder.
Need help to fix it
UPDATE
I've updated the code so it looks like this
[RunWith("org.flexunit.runners.Parameterized")]
public class ArrayBasedStackTests
{
private var foo:Parameterized;
[Parameters]
public static function stacks():Array
{
return [ [new ArrayBasedStack()], [new LinkedListBasedStack()] ] ;
}
[Before]
public function setUp():void
{
}
[After]
public function tearDown():void
{
}
[Test ( description = "Checks isEmpty method of the stack. For empty stack", dataProvider="stacks")]
public function isEmptyStackPositiveTest(stack:IStack):void
{
assertEquals( true, _stack.isEmpty() );
}
It works. But the result is a bit strange. I have 4 test executed instead of 2. (I have 2 items in data provider, so cant get why do I have 4 tests).
Output
http://screencast.com/t/G8DHbcjDUkJ
The [Parameters] meta-data specifies that the parameters are passed to the constructor of the test - so the test class is called for each parameter. You also have the dataProvider set for the specific test method, so the test method is also called once for each parameter. Two calls for the test, and two calls to the method, ends up running four tests.
The solution is to either use [Parameters] meta-tag which specifies the data to use for the whole test class, or use the dataProvider for each test method, but not both with the same data at the same time.
You're missing the static reference to Paramaterized, as shown here:
import org.flexunit.runners.Parameterized;
[RunWith("org.flexunit.runners.Parameterized")]
public class MyTestNGTest
{
private var foo:Parameterized;
...
Basically, that error means that the [Runner] defined isn't available at runtime, which occurs if there is no static reference in the class to cause it to get linked in.
In FlexUnit 4.5.1, this approach changed to using [Rule]'s like so:
public class MyTestNGTest
{
[Rule]
public function paramaterizedRule:ParamaterizedRule = new ParamaterizedRule();
...
}
However, I can't seem to see an actual implementation of IMethodRule for paramaterized tests (that example is fictional).

Moq Verify not checking if a method was called

Hi I am getting an error and I don't understand why
[SetUp]
public void Setup()
{
visitService = new Mock<IVisitService>();
visitRepository = new Mock<IVisitRepository>();
visitUIService = new VisitUIService(visitRepository.Object, visitService.Object);
}
[Test]
public void VisitUIService_CanSoftDelete()
{
Mock<IVisitEntity> mockVisitEntity = new Mock<IVisitEntity>();
visitService = new Mock<IVisitService>();
visitRepository.Setup(x => x.GetVisitsByDocumentLineItems(It.IsAny<IEnumerable<int>>())).Returns(new List<IVisitEntity>() { mockVisitEntity.Object});
visitUIService.DeleteVisits(new VisitDeletionModel());
visitService.Verify(x => x.SoftDeleteVisit(It.IsAny<IVisitEntity>()),Times.AtLeastOnce());
}
Invocation was not performed on the mock: x => x.SoftDeleteVisit(IsAny())
I can't fix this I added visitService.Setup(x => x.SoftDeleteVisit(mockVisitEntity.Object)).Verifiable(); and a few other variations of the parameters but no luck
thank you
I think the problem is the consuming object visitUIService is already been initialized with the intial mocked interfaces and the setup that you are doing later is not useful.
Two approaches:
a) move the initialization of the class to the test i.e after the interface is setup
b) Lazy Load the mocks as follows, but you need to modify your class for the same using Func or Lazy. I will show it using Func
visitUIService = new VisitUIService(()=>visitRepository.Object, ()=>visitService.Object);

Resources