I'm just learning Java and could use your help. I'm using Eclipse, and created a Maven project using the org.openjfx archetype. Everything seems to work fine except when I try to write tests in src/test/java, which causes an error.
An error occurred while instantiating class
starcraft.warcraft.test.TestClass: Unable to make public
starcraft.warcraft.test.TestClass() accessible: module
starcraft.warcraft does not "exports starcraft.warcraft.test" to
module org.testng
This is how I created the project with default settings in Eclipse:
Project Setup with Maven Archetype Selection
Now, when Eclipse creates the project, it doesn't have a src/test/java folder, so I create that manually. Then I create a class called "TestClass" inside a package "starcraft.warcraft.test" inside src/test/java, and I add a simple method to test inside the App class called "adder". You can see the project structure
Project Structure
package starcraft.warcraft;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class App extends Application {
#Override
public void start(Stage stage) {
var javaVersion = SystemInfo.javaVersion();
var javafxVersion = SystemInfo.javafxVersion();
var label = new Label("Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".");
var scene = new Scene(new StackPane(label), 640, 480);
stage.setScene(scene);
stage.show();
}
// WILL TEST THIS METHOD
public static int adder(int digit1, int digit2) {
return digit1 + digit2;
}
public static void main(String[] args) {
launch();
}
}
Now I want to use TestNG for the tests, and so I include it in my POM which is
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>starcraft</groupId>
<artifactId>warcraft</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.5</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.6</version>
<executions>
<execution>
<!-- Default configuration for running -->
<!-- Usage: mvn clean javafx:run -->
<id>default-cli</id>
<configuration>
<mainClass>starcraft.warcraft.App</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
This is the default POM created by the Maven archetype except for the TestNG dependency I added. When I try to use TestNG, Eclipse makes me add it to the module path like so:
Maven saying I need to add the TestNG library
And here is my module-info:
module starcraft.warcraft {
requires javafx.controls;
requires org.testng;
exports starcraft.warcraft;
}
OK, all good so far, but now when I try to run my test inside TestClass:
package starcraft.warcraft.test;
import org.testng.annotations.Test;
import starcraft.warcraft.App;
public class TestClass {
#Test
public void testAdder() {
int sum = App.adder(1, 2);
System.out.println(sum);
}
}
I get the error, which again is
An error occurred while instantiating class
starcraft.warcraft.test.TestClass: Unable to make public
starcraft.warcraft.test.TestClass() accessible: module
starcraft.warcraft does not "exports starcraft.warcraft.test" to
module org.testng
I can't figure out how to do the export. When I try making the entry in module-info, it doesn't give me the option of adding the package in src/test/java, the only packages it allows me to choose from are in src/main/java.
I don't understand modules well. How can I get the program to let me run tests from src/test/java?
Thanks everyone who looked at this. I solved it by following these steps:
Delete module-info.java. This turns it into a nonmodular project which is fine for me. I hesitated to do this because the Maven JavaFX archetype included it, but as it says here somewhere
https://openjfx.io/openjfx-docs/#IDE-Eclipse
you can just delete it after its created.
The problem then if you try to run the project is it will give you a warning that JavaFX isn't included as a module. It will still run, but its best to get rid of this incase of problems down the road. So you need to download the JavaFX libraries, place them in your hard drive, and then include them in your project via VM arguments in Eclipse:
right click project -> Run configuration -> Arguments tab -> add in the VM arguments area something like:
--module-path [fully qualified path to lib folder containing downloaded JavaFX] --add-modules javafx.controls
path would be like "C:\javafx\lib" or wherever you placed the downloaded JavaFX.
Then it should run, and project will still build using Maven, but I'm not sure if its using the JavaFX which is still in the Maven POM or the one I specified on the C drive. But it works. Any help on whats happening there would be appreciated. Thanks
Related
I'm trying to connect to my http://localhost: 8080/spring-boot-test/ui, but unfortunately I fail because I have errors on Eclips. WildFly 23 theoretically worked, because I normally get their localhost
An internal error occurred during: "Updating Deployment Scanners for Server: WildFly 23".
Could not initialize class org.wildfly.security.auth.client.DefaultAuthenticationContextProvider
An internal error occurred during: "Checking Deployment Scanners for server".
Could not initialize class org.wildfly.security.auth.client.DefaultAuthenticationContextProvider
When I try to redirect the directory in standalone.xml to a target with META-INF and WEB-INF, I come across two ERRORs
ERROR [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 1) WFLYDS0011: The deployment scanner found a directory named META-INF that was not inside a directory whose name ends with .ear, .jar, .rar, .sar or .war. This is likely the result of unzipping an archive directly inside the C:\Users\adame\eclipse-workspace\spring-boot-test\target directory, which is a user error. The META-INF directory will not be scanned for deployments, but it is possible that the scanner may find other files from the unzipped archive and attempt to deploy them, leading to errors.
ERROR [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 1) WFLYDS0011: The deployment scanner found a directory named WEB-INF that was not inside a directory whose name ends with .ear, .jar, .rar, .sar or .war. This is likely the result of unzipping an archive directly inside the C:\Users\adame\eclipse-workspace\spring-boot-test\target\ directory, which is a user error. The WEB-INF directory will not be scanned for deployments, but it is possible that the scanner may find other files from the unzipped archive and attempt to deploy them, leading to errors.
Pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.adamkaim.spring</groupId>
<artifactId>spring-boot-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<properties>
<java.version>16</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<packaging>war</packaging>
</project>
App.java
package com.adamkaim.spring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
Address.java
package com.adamkaim.spring;
import org.springframework.stereotype.Component;
#Component
public class Address {
private String address="Wall Street 34";
public String getAddress() {
return this.address;
}
}
Student.java
package com.adamkaim.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class Student {
#Autowired
private Address address;
public String showInfo(){
return this.address.getAddress();
}
}
MainView.java
package com.adamkaim.spring;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.Title;
import com.vaadin.server.VaadinRequest;
import com.vaadin.spring.annotation.SpringUI;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
#SuppressWarnings("serial")
#SpringUI(path="/ui")
#Title("Titlett")
#Theme("valo")
public class MainView extends UI{
#Override
protected void init(VaadinRequest request) {
final VerticalLayout verticalLayout = new VerticalLayout();
verticalLayout.addComponent(new Label("Welcome"));
Button button = new Button("Click me");
verticalLayout.addComponent(button);
button.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
verticalLayout.addComponent(new Label("Button is clicked.."));
}
});
setContent(verticalLayout);
}
}
I was having the same error when trying to start a Wildfly 19.1.0 container from Eclipse (2021-09). The container seemed to start successful, but this message was driving me crazy.
After a while I came across this message on the Wildfly Google Groups, and this solved my problems!
Adding --add-opens=java.base/java.security=ALL-UNNAMED to eclipse.ini
fixed the issue on my side
Thanks to the original author, Rahim Alizada, in https://groups.google.com/g/wildfly/c/_OuPrpsF2pY/m/xLt6u-IfBgAJ.
The option --add-opens opens up the informed modules (all types and members) at runtime, allowing deep reflection from the target modules (in this case, everyone else - ALL-UNNAMED).
More about this option in the JEP 261.
I tried running Eclipse with only Java 8 in my system, if I remember it well I got it working, but some modules on these newer Eclipse versions require Java 11 to load properly.
I came across this error during the deployment of wildfly 23 server in eclipse
An internal error occurred during: "Updating Deployment Scanners for Server: WildFly 23". Could not initialize class org.wildfly.security.auth.client.DefaultAuthenticationContextProvider
This solved my issue too
Adding --add-opens=java.base/java.security=ALL-UNNAMED to eclipse.ini
I use Maven on my test project and I wanted to test test option in Maven's lifecycle, but my JUnit test failed. I have a class named Arithmetics in src.main.java package and a class named ArithmeticsTest in src.test.java package.
When I run ArithmeticsTest on my own using IntelliJ IDEA everything works OK, and I have expected java.lang.AssertionError, so why I don't have such when I run test option in maven?
Console output:
T E S T S
Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
src.main.java.Arithmetics.java
public class Arithmetics
{
public static int add(int a, int b)
{
return a + b;
}
}
src.test.java.ArithmeticsTest.java
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class ArithmeticsTest
{
#Test
public void testAdd()
{
assertEquals(4, Arithmetics.add(2, 3));
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>groupId</groupId>
<artifactId>Test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>15</maven.compiler.source>
<maven.compiler.target>15</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
There are three wrong things I can spot based on your question, while they might not provide a complete answer I hope they'll will be a step in a right direction:
src/main/java and src/test/java is not a package as you write. Its a folder layout supported by maven, basically , if you have a code in com.myorg.somepackage.Arithmetics
Make sure you have the following layout at the level of actual physical folders:
src
main
java
com
myorg
somepackage
Arithmetics.java
test
java
com
myorg
somepackage
ArithmeticsTest.java
For both java files the package must be com.myorg.somepackage:
package com.myorg.somepackage;
public class Arithmetics {}
And
package com.myorg.somepackage;
public class ArithmeticsTest {}
I know it might be a wrong naming that you've used in the question, but still I have to state it because it might cause an actual issue
The second issue is that for some reason you seem to configure your surefire plugin to use test ng which is an alternative to junit. It can happen because testng is placed as a dependency - I can only speculate because you don't really show the full surefire plugin configure and do not provide a full list of dependencies, but you've got and idea I believe :)
This is wrong because you use the junit5 dependencies as well as the imports that correspond to the junit 5.
The dependencies on the junit 5 are completely messy:
You seem to have two dependencies on just the same with the different scope, its really a wrong thing to do. Make sure you use only the test scope and have all the relevant dependencies. Read here for instruction of how to configure the surefire plugin
In addition, for the sake of completeness of the answer, check that you use the recent version of surefire plugin, if its too old the chances are that it won't be able to run jupiter engine (junit 5)
As other answer already pointed out few things which may go wrong in your case, I am just adding the solution to your pom xml.
The surefire plugin version is the main culprit. Default with maven (2.12.4) will not work with junit-5 jupiter engine.
So just add the plugin in your with version 2.22.1 in your pom, it should work after that, assuming your folder structure as per required (see other answer).
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
</plugins>
</pluginManagement>
</build>
I have Spring Boot project with simple EnvironmentPostProcessor implementation:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
public class DevProfilerResolverEnvironmentPostProcessor implements EnvironmentPostProcessor {
#Override
public void postProcessEnvironment(ConfigurableEnvironment configurableEnvironment, SpringApplication springApplication) {
if (configurableEnvironment.getActiveProfiles().length == 0) {
if (System.getenv().get("OS").contains("Windows")) {
configurableEnvironment.addActiveProfile("DEV");
}
}
}
}
Also, I registered this class to sprig.factories:
org.springframework.boot.env.EnvironmentPostProcessor = com.example.demo.DevProfilerResolverEnvironmentPostProcessor
Now structure looks like:
Snippet from pom file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
I executed with Maven:
mvn install
Now I want to use this EnvironmentPostProcessor implementation on another spring boot project. Thus I added it to dependency section for the new project:
<dependency>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
And I wrote simple service usage:
#Service
#Profile("DEV")
public class DeveloperService {
#Scheduled(cron = "1/1 * * * * ?")
public void doWork() {
System.out.println("Developers.... ");
}
}
and enabled scheduling for main class:
#SpringBootApplication
#EnableScheduling
public class LvivBootApplication {
public static void main(String[] args) {
SpringApplication.run(LvivBootApplication.class, args);
}
}
However, I got following exception after main execution:
14:56:09.822 [main] ERROR org.springframework.boot.SpringApplication - Application startup failed
java.lang.IllegalArgumentException: Unable to instantiate factory class: org.springframework.boot.env.EnvironmentPostProcessor
Caused by: java.lang.ClassNotFoundException: com.example.demo.DevProfilerResolverEnvironmentPostProcessor
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
and dependency is added to the new project:
I am running it exactly on Windows environment.
The idea is when OS is Windows add DEV profile for the first project.
Second has service which prints to console dummy info when the profile is DEV and scheduled this printing for every second.
I can't find what is missed at this example?
SOLUTION:
For making from first project library jar pom should be fixed like following:
<!--<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>-->
Or simple to eliminate this plugin from pom file.
Your first jar is not a library jar. It's a repackaged boot jar, created by the spring boot plugin, containing the first spring boot application and all its dependencies, intended to be executed, and not to be used as a library.
If you want to use that as a library, you need to use the non-repackaged jar file, containing only the classes and resources of the project.
It's quite bizarre to have an application depend on another application, though. You should create a library project, only containing common common classes and resources, and use that as a dependency to your two spring boot applications.
I am posting because I had a similar error in similar circumstances - I searched for hours and the solution was very easy. I am using Eclipse for debugging - Eclipse doesn't use the produced jar from Maven build - it uses its own set of build paths with, as far as i understood, exploded classes etc.
My Maven project, the one that produced a JAR that I was including into my main project POM, didn't declare in any way some kind of dependency to the main project, e.g. via a common parent or whatever.
Eclipse seems to not understand that one of the dependencies I was using in the POM was a result of another local project - somehow, although the file (jar-with-dependencies) was in the Maven cache alright, it wasn't picking it up to copy to its own aforementioned set of classpath directories.
I needed to explicitly add it (my library project) into the main project via Project -> Properties -> Java Build Path -> Projects - adding it to the list titled "Required projects on the build path:"
I have seen this question posted here before and I have looked at the solutions however I cannot fix the problem I'm having. I created a very simple Maven project in Eclipse for Java and I want to run the output jar file e.g. java -jar jarfilename.jar
I can run the program by right clicking on the project in eclipse and indicating run as Java application. I can build the project to a jar file with mvn package. Running the jar file I get the output of NoClassDefFoundError for the joda time. The joda jar files are in the configured repository e.g. .m2/repository/joda-time/joda-time/2.8.2. There are no errors indicated for the project in Eclipse. I'm using jdk1.8.0_92 Maven version 3.3.9 and eclipse Java EE Neon release 4.6.0. Java home is configured in the environment variables and so too is the class path as: ...\Java\jdk1.8.0_92\jre\lib;C:\Users\username.m2\repository
Some additional information the classpath is correct in terms of not having typos in it. I also looked at a solution from another similar question wherein the suggestion was to add the external jar to the bootstrap entries under run configuratotion. I have also made an entry in the Java build path for joda time which points corretly to the .m2/repository.../joda-time/2.8.2 What this seems like is that when this runs from eclipse the path to the joda time jar file is (for lack of a better term) known. When the jar file is built however that path is not known. I opened the jar file and looked at the MANIFEST.MF file and I see:
Manifest-Version: 1.0
Built-By: John
Class-Path: joda-time-2.8.jar
Build-Jdk: 1.8.0_92
Created-By: Maven Integration for Eclipse
Main-Class: hello.HelloMain
The source is very simple:
package hello;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
public class HelloMain {
public static void main(String[] args) {
System.out.println("Hello From My Main ! It worked\n");
final DateTime today = new DateTime().withZone(DateTimeZone.UTC);
DateTime tommorrow = today.plusDays(3);
String startTime = today.toString(DateTimeFormat.forPattern("yyyy-MM- dd'T'HH:mm'Z"));
String endTime = tommorrow.toString(DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm'Z"));
System.out.printf("The start time %s End Time %s \n", startTime, endTime);
}
}
This is my pom file:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>hello</groupId>
<artifactId>hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>hello.HelloMain</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.8</version>
</dependency>
After trying many different approaches to the Pom file I had settled on a different approach. This would only apply if your using Eclipse to do this as Eclipse offers an Export to runnable jar feature. While in Eclipse highlight your project of interest, right click to Export and select Java/Runnable JAR file. Click next and select "Package required libraries into generated JAR". This built the jar file with all of the required jar files I needed. While this really does not solve the problem from the perspective of creating the output jar using the maven packaging it did provide a proper executable jar file.
Though I have read many, but many articles on how to use JBehave, I can't get it to work. Here are the steps I went through so far:
Created new Java Project
Downloaded JBehave JAR file version 3.6.8 and added it to my build path libraries
Created a package called com.wmi.tutorials.bdd.stack.specs under the test source folder in my workspace
Added the JBehave JAR file to my Build path Library configuration
Created a JBehave story in the above-mentioned package (StackBehaviourStories.story)
Created a Java class in the above-mentioned package (StackBehaviourStory.java)
Created a Java class in the above-mentioned package (StackBehaviourSteps.java)
Imported the Given, Named, Then, When annotations in my Java class
Written two different scenarios in my JBehave story file
And still, I can't get it to work/run! =(
The story file:
Narrative:
In order to learn to with JBehave using Eclipse
As a junior Java developer though senior in .Net and in BDD
I want to define the behaviour of a custom stack
Scenario: I push an item onto the stack
Given I have an empty stack
When I push an item 'orange'
Then I should count 1
Scenario: I pop from the stack
Given I have an empty stack
When I push an item 'apple'
And I pop the stack
Then I should count 0
The story class
package com.wmi.tutorials.bdd.stack.specs
import org.jbehave.core.configuration.MostUsefulConfiguration;
import org.jbehave.core.junit.JUnitStory;
public class StackBehaviourStory extends JUnitStory {
#Override
public Configuration configuration() { return new MostUsefulConfiguration(); }
#Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration()
, new StackBehaviourSteps());
}
}
The steps class
package com.wmi.tutorials.bdd.stack.specs
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Named;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;
import org.jbehave.core.junit.Assert;
public class StackBehaviourSteps {
#Given("I have an empty stack")
public void givenIHaveAnEmptyStack() { stack = new CustomStack(); }
#When("I push an item $item")
public void whenIPushAnItem(#Named("item") String item) { stack.push(item); }
#Then("I should count $expected")
public void thenIShouldCount(#Named("expected") int expected) {
int actual = stack.count();
if (actual != expected)
throw new RuntimeException("expected:"+expected+";actual:"+actual);
}
}
I'm currently using Eclipse Kepler (4.3) JEE with everything I need to use JUnit, Google App Engine, and yes, JBehave is installed correctly following the Eclipse JBehave installation tutorial.
I can't get it to work. So how can I make it work correctly using Eclipse, JBehave and JUnit?
I know I'm late to the party here but I'm posting because this is the info I wish I had a week ago as it would've saved me a lot of pain. I'm very much into the idea of BDD, but am unfortunately finding JBehave's docs to be a bit of a nightmare, especially when it comes to Maven integration. Moreover a lot of the code I found both on their website and elsewhere didn't work. Through trial and error, and lots of tutorials, I was able to piece together the following. It runs both in Maven and Eclipse, has a single binding class that maps stories to step files, and is able to find story files located in src/test/resources.
here is a working pom file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.projectvalis.st1</groupId>
<artifactId>st1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>st1</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgument></compilerArgument>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${failsafe.and.surefire.version}</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-maven-plugin</artifactId>
<version>4.0.2</version>
<executions>
<execution>
<id>run-stories-as-embeddables</id>
<phase>integration-test</phase>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
<ignoreFailureInStories>false</ignoreFailureInStories>
<ignoreFailureInView>false</ignoreFailureInView>
<systemProperties>
<property>
<name>java.awt.headless</name>
<value>true</value>
</property>
</systemProperties>
</configuration>
<goals>
<goal>run-stories-as-embeddables</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-core</artifactId>
<version>4.0.2</version>
</dependency>
</dependencies>
</project>
here is a sample story file
Narrative:
In order to work with files to compress
As a guy who wants to win a bet with cameron
I want to ensure files are ingested and processed in the manner in which the
methods in the ingest class purport to process them.
Scenario: Simple test to give JBehave a test drive
Given a file, a.log
When the caller loads the file as a byte array
Then the byte array that is returned contains the correct number of bytes.
here is a sample step file
package com.projectvalis.compUtils.tests.ingest;
import java.io.File;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Named;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;
import org.jbehave.core.steps.Steps;
import org.junit.Assert;
import com.projectvalis.compUtils.util.fileIO.Ingest;
/**
* BDD tests for the ingest class
* #author funktapuss
*
*/
public class LoadByteSteps extends Steps {
private String fNameS;
private byte[] byteARR;
#Given("a file, $filename")
public void setFileName(#Named("filename") String filename) {
File file = new File(getClass().getResource("/" + filename).getFile());
fNameS = file.getPath();
}
#When("the caller loads the file as a byte array")
public void loadFile() {
byteARR = Ingest.loadFile(fNameS);
}
#Then("the byte array that is returned contains the "
+ "correct number of bytes.")
public void checkArrSize() {
File file = new File(fNameS);
Assert.assertTrue(
"loading error - "
+ "the file and the resultant byte array are different sizes!",
(long)byteARR.length == file.length());
}
}
and here is the generic runner
package com.projectvalis.compUtils.tests.runner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jbehave.core.configuration.Configuration;
import org.jbehave.core.configuration.MostUsefulConfiguration;
import org.jbehave.core.io.CodeLocations;
import org.jbehave.core.io.LoadFromClasspath;
import org.jbehave.core.io.StoryFinder;
import org.jbehave.core.junit.JUnitStories;
import org.jbehave.core.reporters.Format;
import org.jbehave.core.reporters.StoryReporterBuilder;
import org.jbehave.core.steps.InjectableStepsFactory;
import org.jbehave.core.steps.InstanceStepsFactory;
import org.jbehave.core.steps.Steps;
import com.projectvalis.compUtils.tests.ingest.LoadByteSteps;
/**
* generic binder for all JBehave tests. Binds all the story files to the
* step files. works for both Eclipse and Maven command line build.
* #author funktapuss
*
*/
public class JBehaveRunner_Test extends JUnitStories {
#Override
public Configuration configuration() {
return new MostUsefulConfiguration()
.useStoryLoader(
new LoadFromClasspath(this.getClass().getClassLoader()))
.useStoryReporterBuilder(
new StoryReporterBuilder()
.withDefaultFormats()
.withFormats(Format.HTML, Format.CONSOLE)
.withRelativeDirectory("jbehave-report")
);
}
#Override
public InjectableStepsFactory stepsFactory() {
ArrayList<Steps> stepFileList = new ArrayList<Steps>();
stepFileList.add(new LoadByteSteps());
return new InstanceStepsFactory(configuration(), stepFileList);
}
#Override
protected List<String> storyPaths() {
return new StoryFinder().
findPaths(CodeLocations.codeLocationFromClass(
this.getClass()),
Arrays.asList("**/*.story"),
Arrays.asList(""));
}
}
the runner lives in src/test/java//tests.runner.
the ingest test lives in src/test/java//tests.ingest.
the story files live in src/test/resources/stories.
As far as I can tell, JBehave has LOTS of options, so this certainly isn't the only way of doing things. Treat this like a template that will get you up and running quickly.
full source is on github.
Following step by step closely the jbehave Getting Started tutorial, the Run story section says: [...] the ICanToggleACell.java class will allow itself to run as a JUnit test.
This means that the JUnit library is required in your Build path.
Using Eclipse:
Select your current project and right-click it, Build path, Configure Build Path...
Properties for [current project], Java Build Path, Libraries, click [Add Library...]
Add Library, select JUnit, click [Next]
JUnit Library, JUnit library version, select the version you wish to use, click [Finish]
Java Build Path, click [OK]
Project Explorer, select your ICanToggleACell.java class, right-click it, then Run As, and click on JUnit Test
So this is the same here as for the above-example code. The StackBehaviourStory.java class should let itself run as a JUnit test after you add the proper library to the Java build path.
In my case, I have extended my Steps class from Steps (from jbehave core)
i had updated the JunitStory to JunitStories and it worked
public class StackBehaviourStory extends JUnitStory ---> JunitStories