I have:
Eclispse
Version: 2019-06 (4.12.0)
Build id: 20190614-1200
Liferay 7.2.0 CE GA1.
I use Gradle.
I followed this tutorial:
https://www.liferaystack.com/2017/11/rest-extender-and-jax-rs-restful-web-service-in-liferay-7-dxp.html
I created a rest module.
I created two file of configuration inside the folder "src/main/resources/configuration":
com.liferay.portal.remote.cxf.common.configuration.CXFEndpointPublisherConfiguration-cxf.properties
Code:
contextPath=/my-rest-service
authVerifierProperties=auth.verifier.BasicAuthHeaderAuthVerifier.urls.includes=*
com.liferay.portal.remote.rest.extender.configuration.RestExtenderConfiguration-rest.properties
Code:
contextPaths=/my-rest-service
jaxRsServiceFilterStrings=(component.name=com.liferaystack.application.MyRestServiceApplication)
This is the MyRestWebserviceApplication.java:
package com.liferaystack.application;
import java.util.Collections;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Application;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
/**
* #author pinoteam
*/
#ApplicationPath("/my-rest-service")
#Component(immediate = true, service = Application.class)
public class MyRestWebserviceApplication extends Application {
public Set<Object> getSingletons() {
return Collections.<Object>singleton(this);
}
#GET
#Produces("text/plain")
public String working() {
return "It works!";
}
#GET
#Path("/morning")
#Produces("text/plain")
public String hello() {
return "Good morning!";
}
#GET
#Path("/mattina")
#Produces("text/plain")
public String helloGa() {
return "Good morning!";
}
#GET
#Path("/morning/{name}")
#Produces("text/plain")
public String morning(
#PathParam("name") String name,
#QueryParam("drink") String drink) {
String greeting = "Good Morning " + name;
if (drink != null) {
greeting += ". Would you like some " + drink + "?";
}
return greeting;
}
}
I run build and deploy.
The app is active, but nothing work.
In control panel i have not any Rest Extender Configuration and i have not api at any url.
what am i missing? any idea?
The tutorial you link is for Liferay 7.0 - the package/path names of the configuration files might have changed, and I've seen a context path being declared in bnd.bnd, rather than those property files - things might have changed since then.
An alternative starting point might be the blade sample, which is written for 7.2, and provides a Whiteboard-properties in the Java class:
#Component(
property = {
JaxrsWhiteboardConstants.JAX_RS_APPLICATION_BASE + "=/users",
JaxrsWhiteboardConstants.JAX_RS_NAME + "=Users"
},
service = Application.class
)
public class UsersRestService extends Application {
#GET
#Path("/list")
#Produces("text/plain")
public String getUsers() {
...
}
...
That plugin's configuration file is rather trivial (looks optional on first glance, but don't take my word for it)
Related
When following Cubicoder's modding tutorial for Forge 1.12.2, and creating my first item, the texture for the item will not load. I have double checked all of my code against his code. I have my latest log here. I have my registration handler RegistrationHandler.java down below.
package notacyborg.tutorialmod;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraftforge.event.RegistryEvent.Register;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import notacyborg.tutorialmod.util.RegistryUtil;
#EventBusSubscriber(modid = TutorialMod.MODID)
public class RegistrationHandler
{
#SubscribeEvent
public static void registerItems(Register<Item> event)
{
final Item[] items = {
RegistryUtil.setItemName(new Item(), "first_item").setCreativeTab(CreativeTabs.MISC)
};
event.getRegistry().registerAll(items);
}
}
ModelRegistrationHandler.java
package notacyborg.tutorialmod.client;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import notacyborg.tutorialmod.TutorialMod;
import notacyborg.tutorialmod.init.ModItems;
#EventBusSubscriber(value = Side.CLIENT, modid = TutorialMod.MODID)
public class ModelRegistrationHandler
{
#SubscribeEvent
public static void registerModels(ModelRegistryEvent event)
{
registerModel(ModItems.FIRST_ITEM, 0);
}
private static void registerModel(Item item, int meta)
{
ModelLoader.setCustomModelResourceLocation(item, meta,
new ModelResourceLocation(item.getRegistryName(), "inventory"));
}
}
And my first_item.json model file.
{
"parent": "item/generated",
"textures": {
"layer0": "tutorialmod:textures/items/first_item"
}
}
Any help is appreciated!
Your error log says that it was not able to find the model file of your first_item. Make sure that you have put your first_item.json (model file) in assets/Your-Mod-ID/models/item/first_item.json
In your first_item.json file, line 4 should be:
"textures": {
"layer0": "tutorialmod:item/first_item"
}
Try it out and post an error log too if you encounter any further errors.
I tried out all the different method selectors as seen on this page: https://junit.org/junit5/docs/current/api/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.html
For example tried to do it like so:
selectMethod("org.example.order.OrderTests#test3"),
like so:
selectMethod("org.example.order.OrderTests#test3(TestInfo)"),
or like so: selectMethod("org.example.order.OrderTests#test3(org.junit.jupiter.engine.extension.TestInfoParameterResolver$DefaultTestInfo)")
Each time, no tests are found.
When I only select the class the method resides in, it works: selectClass("org.example.order.OrderTests")
(but I'm looking to call the method explicitly)
I am assuming the behavior is the same for other parameter types that are resolved at runtime by a ParameterResolver.
Your assumption is wrong. You can select one and only one test method.
As you mentioned on this page Discovery Selectors there are a lot of examples.
DiscoverySelectors.selectMethod provide three way to select desired method(s)
public static MethodSelector selectMethod(String className, String methodName, String methodParameterTypes) {
...
}
public static MethodSelector selectMethod(String className, String methodName) {
...
}
and
public static MethodSelector selectMethod(String fullyQualifiedMethodName) throws PreconditionViolationException {
...
}
You've tried to use the last method but the fullyQualifiedMethodName was wrong a little bit. If you take a look on javadoc it will turn up.
Parameter type list must exactly match and every non-primitive types must be fully qualified as well.
In your example the package is missing. Try it like: selectMethod("org.example.order.OrderTests#test3(org.junit.jupiter.api.TestInfo)")
Here is a short test.
package io.github.zforgo.stackoverflow;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
public class ClassWithTestInfo {
#Test
void foo() {
}
#Test
void foo(TestInfo info) {
}
#RepeatedTest(3)
void foo(RepetitionInfo info) {
}
}
package io.github.zforgo.stackoverflow;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor;
import org.junit.platform.engine.DiscoverySelector;
import org.junit.platform.engine.FilterResult;
import org.junit.platform.engine.discovery.DiscoverySelectors;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.PostDiscoveryFilter;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.launcher.core.LauncherFactory;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
class DiscoveryTest {
#Test
#DisplayName("Should select only the desired method(s)")
void doTEst() {
Assertions.assertAll(
() -> {
var methods = discover(DiscoverySelectors.selectClass(ClassWithTestInfo.class));
Assertions.assertEquals(3, methods.size());
},
() -> {
// your way
var fqmn = "io.github.zforgo.stackoverflow.ClassWithTestInfo#foo(TestInfo)";
var methods = discover(DiscoverySelectors.selectMethod(fqmn));
Assertions.assertEquals(0, methods.size());
},
() -> {
// good way
var fqmn = "io.github.zforgo.stackoverflow.ClassWithTestInfo#foo(org.junit.jupiter.api.TestInfo)";
var methods = discover(DiscoverySelectors.selectMethod(fqmn));
Assertions.assertEquals(1, methods.size());
}
);
}
private List<Method> discover(DiscoverySelector... selectors) {
final List<Method> methodCollector = new ArrayList<>();
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectors)
.filters((PostDiscoveryFilter) object -> {
Method m = ((MethodBasedTestDescriptor) object).getTestMethod();
methodCollector.add(m);
return FilterResult.included("Matched");
})
.build();
LauncherFactory.create().discover(request);
return methodCollector;
}
}
I'm learning Arquillian right now I wonder how to create page that has a placeholder inside the path. For example:
#Location("/posts/{id}")
public class BlogPostPage {
public String getContent() {
// ...
}
}
or
#Location("/posts/{name}")
#Location("/specific-page?requiredParam={value}")
I have looking for an answer on graphine and arquillian reference guides without success. I used library from other language that have support for page-objects, but it has build-in support for placeholders.
AFAIK there is nothing like this implemented in Graphene.
To be honest, I'm not sure how this should behave - how would you pass the values...?
Apart from that, I think that it could be also limited by Java annotation abilities https://stackoverflow.com/a/10636320/6835063
This is not possible currently in Graphene. I've created ARQGRA-500.
It's possible to extend Graphene to add dynamic parameters now. Here's how. (Arquillian 1.1.10.Final, Graphene 2.1.0.Final.)
Create an interface.
import java.util.Map;
public interface LocationParameterProvider {
Map<String, String> provideLocationParameters();
}
Create a custom LocationDecider to replace the corresponding Graphene's one. I replace the HTTP one. This Decider will add location parameters to the URI, if it sees that the test object implements our interface.
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Map.Entry;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.graphene.location.decider.HTTPLocationDecider;
import org.jboss.arquillian.graphene.spi.location.Scheme;
import org.jboss.arquillian.test.spi.context.TestContext;
public class HTTPParameterizedLocationDecider extends HTTPLocationDecider {
#Inject
private Instance<TestContext> testContext;
#Override
public Scheme canDecide() {
return new Scheme.HTTP();
}
#Override
public String decide(String location) {
String uri = super.decide(location);
// not sure, how reliable this method of getting the current test object is
// if it breaks, there is always a possibility of observing
// org.jboss.arquillian.test.spi.event.suite.TestLifecycleEvent's (or rather its
// descendants) and storing the test object in a ThreadLocal
Object testObject = testContext.get().getActiveId();
if (testObject instanceof LocationParameterProvider) {
Map<String, String> locationParameters =
((LocationParameterProvider) testObject).provideLocationParameters();
StringBuilder uriParams = new StringBuilder(64);
boolean first = true;
for (Entry<String, String> param : locationParameters.entrySet()) {
uriParams.append(first ? '?' : '&');
first = false;
try {
uriParams.append(URLEncoder.encode(param.getKey(), "UTF-8"));
uriParams.append('=');
uriParams.append(URLEncoder.encode(param.getValue(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
uri += uriParams.toString();
}
return uri;
}
}
Our LocationDecider must be registered to override the Graphene's one.
import org.jboss.arquillian.core.spi.LoadableExtension;
import org.jboss.arquillian.graphene.location.decider.HTTPLocationDecider;
import org.jboss.arquillian.graphene.spi.location.LocationDecider;
public class MyArquillianExtension implements LoadableExtension {
#Override
public void register(ExtensionBuilder builder) {
builder.override(LocationDecider.class, HTTPLocationDecider.class,
HTTPParameterizedLocationDecider.class);
}
}
MyArquillianExtension should be registered via SPI, so create a necessary file in your test resources, e.g. for me the file path is src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension. The file must contain a fully qualified class name of MyArquillianExtension.
And that's it. Now you can provide location parameters in a test.
import java.util.HashMap;
import java.util.Map;
import org.jboss.arquillian.graphene.page.InitialPage;
import org.jboss.arquillian.graphene.page.Location;
import org.junit.Test;
public class TestyTest implements LocationParameterProvider {
#Override
public Map<String, String> provideLocationParameters() {
Map<String, String> params = new HashMap<>();
params.put("mykey", "myvalue");
return params;
}
#Test
public void test(#InitialPage TestPage page) {
}
#Location("MyTestView.xhtml")
public static class TestPage {
}
}
I've focused on parameters specifically, but hopefully this paves the way for other dynamic path manipulations.
Of course this doesn't fix the Graphene.goTo API. This means before using goTo you have to provide parameters via this roundabout provideLocationParameters way. It's weird. You can make your own alternative API, goTo that accepts parameters, and modify your LocationDecider to support other ParameterProviders.
I'm using spring 4.2 to create some restfull webservices.
But we realized that when a user mistypes one of the not-mandatory #RequestParam, we do not get an error that the param he passed is unknown.
like we have #RequestParam(required=false, value="valueA") String value A and in the call he uses '?valuueA=AA' -> we want an error.
But I do not seem to find a way to do this, the value is just ignored and the user is unaware of this.
One possible solution would be to create an implementation of HandlerInterceptor which will verify that all request parameters passed to the handler method are declared in its #RequestParam annotated parameters.
However you should consider the disadvantages of such solution. There might be situations where you want to allow certain parameters to be passed in and not be declared as request params. For instance if you have request like GET /foo?page=1&offset=0 and have handler with following signature:
#RequestMapping
public List<Foo> listFoos(PagingParams page);
and PagingParams is a class containing page and offset properties, it will normally be mapped from the request parameters. Implementation of a solution you want would interfere with this Spring MVC'c functionality.
That being said, here is a sample implementation I had in mind:
public class UndeclaredParamsHandlerInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
checkParams(request, getDeclaredRequestParams(handlerMethod));
}
return true;
}
private void checkParams(HttpServletRequest request, Set<String> allowedParams) {
request.getParameterMap().entrySet().forEach(entry -> {
String param = entry.getKey();
if (!allowedParams.contains(param)) {
throw new UndeclaredRequestParamException(param, allowedParams);
}
});
}
private Set<String> getDeclaredRequestParams(HandlerMethod handlerMethod) {
Set<String> declaredRequestParams = new HashSet<>();
MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
for (MethodParameter methodParameter : methodParameters) {
if (methodParameter.hasParameterAnnotation(RequestParam.class)) {
RequestParam requestParam = methodParameter.getParameterAnnotation(RequestParam.class);
if (StringUtils.hasText(requestParam.value())) {
declaredRequestParams.add(requestParam.value());
} else {
methodParameter.initParameterNameDiscovery(parameterNameDiscoverer);
declaredRequestParams.add(methodParameter.getParameterName());
}
}
}
return declaredRequestParams;
}
}
Basically this will do what I described above. You can then add exception handler for the exception it throws and translate it to HTTP 400 response. I've put more of an complete sample on Github, which includes a way to selectively enable this behavior for individual handler methods via annotation.
I translated Bohuslav Burghardt's solution for Spring WebFlux applications.
I dropped the #DisallowUndeclaredRequestParams annotation class from GitHub because I didn't need it -- it just applies the filter to all HandlerMethods. But someone else could update this answer and put it back.
package com.example.springundeclaredparamerror;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
/**
* Handler interceptor used for ensuring that no request params other than those explicitly
* declared via {#link RequestParam} parameters of the handler method are passed in.
*/
// Implementation translated into WebFlux WebFilter from:
// https://github.com/bohuslav-burghardt/spring-sandbox/tree/master/handler-interceptors/src/main/java/handler_interceptors
#Component
public class DisallowUndeclaredParamsFilter implements WebFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(DisallowUndeclaredParamsFilter.class);
#Autowired
#Qualifier("requestMappingHandlerMapping")
RequestMappingHandlerMapping mapping;
#Autowired
ObjectMapper mapper;
#Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
Object o = mapping.getHandler(serverWebExchange).toFuture().getNow(null);
Optional<String> undeclaredParam = Optional.empty();
if (o != null && o instanceof HandlerMethod) {
var handlerMethod = (HandlerMethod) o;
undeclaredParam = checkParams(serverWebExchange.getRequest(),
getDeclaredRequestParams(handlerMethod));
}
return undeclaredParam.map((param) -> RespondWithError(serverWebExchange, param))
.orElseGet(() -> webFilterChain.filter(serverWebExchange));
}
/** Responds to the request with an error message for the given undeclared parameter. */
private Mono<Void> RespondWithError(ServerWebExchange serverWebExchange, String undeclaredParam) {
final HttpStatus status = HttpStatus.BAD_REQUEST;
serverWebExchange.getResponse().setStatusCode(status);
serverWebExchange.getResponse().getHeaders().add(
"Content-Type", "application/json");
UndeclaredParamErrorResponse response = new UndeclaredParamErrorResponse();
response.message = "Parameter not expected: " + undeclaredParam;
response.statusCode = status.value();
String error = null;
try {
error = mapper.writeValueAsString(response);
} catch (JsonProcessingException e) {
error = "Parameter not expected; error generating JSON response";
LOGGER.warn("Error generating JSON response for undeclared argument", e);
}
return serverWebExchange.getResponse().writeAndFlushWith(
Mono.just(Mono.just(serverWebExchange.getResponse().bufferFactory().wrap(
error.getBytes(StandardCharsets.UTF_8)))));
}
/** Structure for generating error JSON. */
static class UndeclaredParamErrorResponse {
public String message;
public int statusCode;
}
/**
* Check that all of the request params of the specified request are contained within the specified set of allowed
* parameters.
*
* #param request Request whose params to check.
* #param allowedParams Set of allowed request parameters.
* #return Name of a param in the request that is not allowed, or empty if all params in the request are allowed.
*/
private Optional<String> checkParams(ServerHttpRequest request, Set<String> allowedParams) {
return request.getQueryParams().keySet().stream().filter(param ->
!allowedParams.contains(param)
).findFirst();
}
/**
* Extract all request parameters declared via {#link RequestParam} for the specified handler method.
*
* #param handlerMethod Handler method to extract declared params for.
* #return Set of declared request parameters.
*/
private Set<String> getDeclaredRequestParams(HandlerMethod handlerMethod) {
Set<String> declaredRequestParams = new HashSet<>();
MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
for (MethodParameter methodParameter : methodParameters) {
if (methodParameter.hasParameterAnnotation(RequestParam.class)) {
RequestParam requestParam = methodParameter.getParameterAnnotation(RequestParam.class);
if (StringUtils.hasText(requestParam.value())) {
declaredRequestParams.add(requestParam.value());
} else {
methodParameter.initParameterNameDiscovery(parameterNameDiscoverer);
declaredRequestParams.add(methodParameter.getParameterName());
}
}
}
return declaredRequestParams;
}
}
Here's the unit test I wrote for it. I recommend checking it into your codebase as well.
package com.example.springundeclaredparamerror;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
#RunWith(SpringRunner.class)
#WebFluxTest(controllers = {DisallowUndeclaredParamFilterTest.TestController.class})
public class DisallowUndeclaredParamFilterTest {
private static final String TEST_ENDPOINT = "/disallowUndeclaredParamFilterTest";
#Rule
public final WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort());
#Autowired
private WebTestClient webClient;
#Configuration
#Import({TestController.class, DisallowUndeclaredParamsFilter.class})
static class TestConfig {
}
#RestController
static class TestController {
#GetMapping(TEST_ENDPOINT)
public Mono<String> retrieveEntity(#RequestParam(name = "a", required = false) final String a) {
return Mono.just("ok");
}
}
#Test
public void testAllowsNoArgs() {
webClient.get().uri(TEST_ENDPOINT).exchange().expectBody(String.class).isEqualTo("ok");
}
#Test
public void testAllowsDeclaredArg() {
webClient.get().uri(TEST_ENDPOINT + "?a=1").exchange().expectBody(String.class).isEqualTo("ok");
}
#Test
public void testDisallowsUndeclaredArg() {
webClient.get().uri(TEST_ENDPOINT + "?b=1").exchange().expectStatus().is4xxClientError();
}
}
I'm trying to set up JBehave for testing web services.
Template story is running well, but I can see in JUnit Panel only Acceptance suite class execution result. What I want is to see execution result for each story in suite and for each step in story like it is shown in simple JUnit tests or in Thucydides framework.
Here is my acceptance suite class: so maybe I Haven't configured something, or either I have to notate my step methods some other way, but I didn't find an answer yet.
package ***.qa_webservices_testing.jbehave;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import org.jbehave.core.Embeddable;
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.parsers.RegexPrefixCapturingPatternParser;
import org.jbehave.core.reporters.CrossReference;
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.ParameterConverters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ***.qa_webservices_testing.jbehave.steps.actions.TestAction;
/**
* suite class.
*/
public class AcceptanceTestSuite extends JUnitStories {
private static final String CTC_STORIES_PATTERN = "ctc.stories";
private static final String STORY_BASE = "src/test/resources";
private static final String DEFAULT_STORY_NAME = "stories/**/*.story";
private static final Logger LOGGER = LoggerFactory.getLogger(AcceptanceTestSuite.class);
private final CrossReference xref = new CrossReference();
public AcceptanceTestSuite() {
configuredEmbedder()
.embedderControls()
.doGenerateViewAfterStories(true)
.doIgnoreFailureInStories(false)
.doIgnoreFailureInView(true)
.doVerboseFailures(true)
.useThreads(2)
.useStoryTimeoutInSecs(60);
}
#Override
public Configuration configuration() {
Class<? extends Embeddable> embeddableClass = this.getClass();
Properties viewResources = new Properties();
viewResources.put("decorateNonHtml", "true");
viewResources.put("reports", "ftl/jbehave-reports-with-totals.ftl");
// Start from default ParameterConverters instance
ParameterConverters parameterConverters = new ParameterConverters();
return new MostUsefulConfiguration()
.useStoryLoader(new LoadFromClasspath(embeddableClass))
.useStoryReporterBuilder(new StoryReporterBuilder()
.withCodeLocation(CodeLocations.codeLocationFromClass(embeddableClass))
.withDefaultFormats()
.withViewResources(viewResources)
.withFormats(Format.CONSOLE, Format.TXT, Format.HTML_TEMPLATE, Format.XML_TEMPLATE)
.withFailureTrace(true)
.withFailureTraceCompression(false)
.withMultiThreading(false)
.withCrossReference(xref))
.useParameterConverters(parameterConverters)
// use '%' instead of '$' to identify parameters
.useStepPatternParser(new RegexPrefixCapturingPatternParser(
"%"))
.useStepMonitor(xref.getStepMonitor());
}
#Override
protected List<String> storyPaths() {
String storiesPattern = System.getProperty(CTC_STORIES_PATTERN);
if (storiesPattern == null) {
storiesPattern = DEFAULT_STORY_NAME;
} else {
storiesPattern = "**/" + storiesPattern;
}
LOGGER.info("will search stories by pattern {}", storiesPattern);
List<String> result = new StoryFinder().findPaths(STORY_BASE, Arrays.asList(storiesPattern), Arrays.asList(""));
for (String item : result) {
LOGGER.info("story to be used: {}", item);
}
return result;
}
#Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration(), new TestAction());
}
}
my test methods look like:
Customer customer = new cutomer();
#Given ("I have Access to Server")
public void givenIHaveAccesToServer() {
customer.haveAccesToServer();
}
So they are notated only by JBehave notations.
The result returned in Junit panel is only like here (I yet have no rights to post images):
You should try this open source library:
https://github.com/codecentric/jbehave-junit-runner
It does exactly what you ask for :)
Yes, the codecentric runner works very nicely.
https://github.com/codecentric/jbehave-junit-runner