Is there a way to have a seperate featurecontext file for different features - behat

I am new to behat and noticed that every .feature file I create gets added to the FeatureContext.php when I run --dry-run --append-snippets
on the command line
But its going to get messy if I have tons of tests in the FeatureContext.php file
Is there a way where I can have a different "FeatureContext" class set up for different .feature files?
Thank you!

Easy way!
class FeatureContext extends MinkContext implements KernelAwareInterface
{
}
class MessageContext extends FeatureContext
{
}
class MailContext extends FeatureContext
{
}
Or you can do this way:
class FeatureContext extends MinkContext implements KernelAwareInterface
{
public function __construct(array $parameters)
{
$this->useContext('message_context', new MessageContext());
$this->useContext('mail_context', new MailContext());
}
}

Related

How to define pointcut for class initialization

I'm a newbie to AspectJ, and trying to understand joinpoint model
Now i have class like this
public class Account {
private static Map<String, PaymentMethod> supportedPayments = new HashMap<>();
static {
supportedPayments.add("COD", new CodPaymentMethod());
supportedPayments.add("ATM", new ATMPaymentMethod());
}
}
as i read from AspectJ In Action, there is a way to define pointcut when class is intialization, but i could not find syntax.
Anyone help me?
This one does not work:
#Pointcut("initialization(com.jas.aop.bean.Payment"))
it say
ERROR] Syntax error on token "initialization(com.jas.aop.bean.Payment)", "name pattern" expected
/Users/admin/eclipse-workspace/aop/src/main/java/com/jas/aop/aspect/ClassInitializationAspect.java:9
#Pointcut("initialization(com.jas.aop.bean.Payment)")
Your pointcut has several problems:
There is a missing closing parenthesis ).
initialization intercepts constructors (i.e. object initialisation) rather than static class initialisation, which is not what you want and also would require a constructor pattern, not a class name pattern.
If your aspect does not happen to be in the exact same package as the target class, you must use a fully qualified class name such as my.package.Account in order to make the pointcut match.
By the way, your code snippets are just pseudo code because a hash map does not have an add method, rather a put method. The sample class does not even compile. Don't just invent code when posting questions here. Make life easier for the people trying to help you.
Now here is an MCVE, something I always suggest you to specify in your question in order to help people reproduce your situation. I did it for you this time, this was your free shot. Next time, please do it yourself.
Dependency classes used by the main class:
package de.scrum_master.app;
public interface PaymentMethod {}
package de.scrum_master.app;
public class ATMPaymentMethod implements PaymentMethod {}
package de.scrum_master.app;
public class CodPaymentMethod implements PaymentMethod {}
Target class with driver application:
package de.scrum_master.app;
import java.util.HashMap;
import java.util.Map;
public class Account {
private static Map<String, PaymentMethod> supportedPayments = new HashMap<>();
static {
System.out.println("Static initialiser block");
supportedPayments.put("COD", new CodPaymentMethod());
supportedPayments.put("ATM", new ATMPaymentMethod());
}
public Account() {
System.out.println("Creating account");
}
public void doSomething() {
System.out.println("Doing something");
}
public static void main(String[] args) {
new Account().doSomething();
}
}
Aspect:
The aspect shows both initialization and staticinitialization in order to show the difference in both syntax and functionality. You can find all of this explained with examples in the AspectJ manual, which I warmly recommend you to read.
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class AccountAspect {
#Before("initialization(de.scrum_master.app.Account.new(..))")
public void interceptObjectInitialisation(JoinPoint joinPoint) {
System.out.println(joinPoint);
}
#Before("staticinitialization(de.scrum_master.app.Account)")
public void interceptClassInitialisation(JoinPoint joinPoint) {
System.out.println(joinPoint);
}
}
Console log:
staticinitialization(de.scrum_master.app.Account.<clinit>)
Static initialiser block
initialization(de.scrum_master.app.Account())
Creating account
Doing something

Resteasy and Google Guice: how to use multiple #ApplicationPath and resource with #Injection?

I created a project to test the dependency injection offered by Google Guice in my Jax-rs resources, using Resteasy.
My intentions are:
Use multiple #ApplicationPath for the versions of my API. In each class annotated with #ApplicationPath I load a set of classes for the specific version.
Each resource have a #Inject (from Google Guice) in his constructor to inject some services.
I created two classes annotated with #ApplicationPath: ApplicationV1RS and ApplicationV2RS. In both I added the same resources classes (UserResource and HelloResource), only for my test.
My Module is configured like this:
public class HelloModule implements Module
{
public void configure(final Binder binder)
{
binder.bind(IGreeterService.class).to(GreeterService.class);
binder.bind(IUserService.class).to(UserService.class);
}
}
When I call http://localhost:9095/v1/hello/world or http://localhost:9095/v2/hello/world, I receive the same error:
java.lang.RuntimeException: RESTEASY003190: Could not find constructor
for class: org.jboss.resteasy.examples.guice.hello.HelloResource
Well, as I expected, this not works. The Google Guice is not "smart" to instantiate the resource classes using the construtor for me.
But I can't find a way to work. To be really honest, I'm really confuse about how the Google Guice, Jetty and Resteasy play with each other in this scenario.
If I abandon the idea of use #ApplicationPath, my resources work with Google Guice configuring my HelloModule like this:
public class HelloModule implements Module
{
public void configure(final Binder binder)
{
binder.bind(HelloResource.class);
binder.bind(IGreeterService.class).to(GreeterService.class);
binder.bind(UserResource.class);
binder.bind(IUserService.class).to(UserService.class);
}
}
But in this case, I'm passing the control to register my resources (HelloResource and UserResource) to Guice. It's not flexible for me, I can't setup my multiple #ApplicationPath.
So, what I'm missing or not understanding?
I created a project with the problemetic code. Is very easy to setup and test: https://github.com/dherik/resteasy-guice-hello/tree/so-question/README.md
Thanks!
When you have getClasses method in your Application then it tries to create instance for all the registered resources using the default constructor which is missing in our Resources class. One way is to create a default constructor and Inject the dependencies through setter Injection.
And then instead of overriding getClasses in ApplicationV1RS and ApplicationV2RS you override getSingletons. Since Resources can be Singleton.
Below are the changes that I made to make it work the way you want.
ApplicationV1RS.java
#ApplicationPath("v1")
public class ApplicationV1RS extends Application {
private Set<Object> singletons = new HashSet<Object>();
public ApplicationV1RS(#Context ServletContext servletContext) {
}
#Override
public Set<Object> getSingletons() {
Injector injector = Guice.createInjector(new HelloModule());
HelloResource helloResource = injector.getInstance(HelloResource.class);
UserResource userResource = injector.getInstance(UserResource.class);
singletons.add(helloResource);
singletons.add(userResource);
return singletons;
}
}
ApplicationV2RS.java
#ApplicationPath("v2")
public class ApplicationV2RS extends Application {
private Set<Object> singletons = new HashSet<Object>();
public ApplicationV2RS(#Context ServletContext servletContext) {
}
#Override
public Set<Object> getSingletons() {
Injector injector = Guice.createInjector(new HelloModule());
HelloResource helloResource = injector.getInstance(HelloResource.class);
UserResource userResource = injector.getInstance(UserResource.class);
singletons.add(helloResource);
singletons.add(userResource);
return singletons;
}
}
HelloResource.java
#Path("hello")
public class HelloResource {
#Inject
private IGreeterService greeter;
public HelloResource() {
}
#GET
#Path("{name}")
public String hello(#PathParam("name") final String name) {
return greeter.greet(name);
}
}
UserResource.java
#Path("user")
public class UserResource {
#Inject
private IUserService userService;
public UserResource() {
}
#GET
#Path("{name}")
public String hello(#PathParam("name") final String name) {
return userService.getUser(name);
}
}
Add #Singleton to your Service Classes.
Hope it helps.
I have also pushed the code to forked repo. check it out

Kotlin: Visibility of static nested Java class declared inside a non-visible class

Using java my static-nested java class is visible, but using Kotlin it is not. See my example below. Is there a good reason it is not allowed, or is it a bug? And are there any workarounds so that I can extend NestedStaticClass from Kotlin?
I have a package-private java class containing the static-nested class
package javapackage;
class HiddenClass {
public static class NestedStaticClass {}
}
HiddenClass is extended by a public class.
package javapackage;
public class VisibleClass extends HiddenClass{}
From my java class extending VisibleClass, I can see NestedStaticClass (It compiles)
package otherpackage;
import javapackage.VisibleClass;
public class JavaClass extends VisibleClass {
public static class C4 extends NestedStaticClass {}
public JavaClass() {
new NestedStaticClass();
}
}
But from Kotlin this does not work. I get the compile error: "Unresolved reference NestedStaticClass"
package otherpackage
import javapackage.VisibleClass
class KotlinClass() : VisibleClass() {
class C1() : NestedStaticClass()
init {
val v = NestedStaticClass()
}
}

Refactoring JUnit rules from tests

I have several tests and using junit with them. In all my test files I have the junit #Rule statements. like:
public #Rule
TestWatcher resultReportingTestWatcher = new TestWatcher(this);
This and few other statements exist in all my test files. This repetion of code bothers me a little, since I think these lines can be moved to a separate place and can be used from there.
I am not very sure if this can be done, as I am very new to junit.
Need giudence.
You can put common Rules in a parent class:
public class AbstractTest {
#Rule public SomeRule someRule = new SomeRule();
}
public class YourTest extends AbstractTest {
#Test public void testMethod() {
someRule.blah();
// test some things
}
}

Playframework 2.1 Japid global variable

May i know how to init global variables in play framework? if can show in Japid is the best.
Appreciate your help.
Thanks
I found the solution.
Below is my example:
I create a class and extends to Action.Simple
package common;
import play.Play;
import play.mvc.Action;
import play.mvc.Http.Context;
import play.mvc.Result;
public class Init extends Action.Simple{
#Override
public Result call(Context ctx) throws Throwable {
ctx.args.put("resourcesurl", Play.application().configuration().getString("resources.url"));
return delegate.call(ctx);
}
}
and this is my controller:
#With(Init.class)
public class Museum extends JapidController{
public static Result nes(){
return renderJapid();
}
}
at my html:
<img src="${Context.current().args.get("resourcesurl")}/resources/test.jpg"/>
hope this help others as well.