How do i initiate Spring #Autowired instances when running a Cucumber test? - java

I'm able to initiate Spring when i'm debbuging StepDefinitions.java, but running the test from gradle produces null. Do I need an aditional glue?
Produces null: gradle cucumber
Produces null: running myFeature.features
Produces myService (working): running Stepdefinitions.java
I have tried the following code:
#ContextConfiguration(
classes = Application.class,
loader = SpringBootContextLoader.class)
#WebAppConfiguration
Current StepDefinitions:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = Application.class)
#WebAppConfiguration
public class StepDefinitions{
private static String roll;
#Autowired
MyService myService;
/** Reset all static values before running test cases */
#BeforeClass
public static void resetValues() {
roll = "";
}
//I use swedish, "Given"
#Givet("Jag har rollen {string}")
public void getRole(String roll) {
assertNotNull(roll);
this.roll = roll;
myService.useRole(roll);
}
}
gradle.build:
dependencies {
compile files('../libs/cucumber-spring-4.7.1.jar')
testCompile 'io.cucumber:cucumber-java:' + cucumberVersion
testCompile 'io.cucumber:cucumber-junit:' + cucumberVersion
...
}
task cucumber() {
dependsOn assemble, compileTestJava
doLast {
javaexec {
main = "cucumber.api.cli.Main"
classpath = configurations.cucumberRuntime +
sourceSets.main.output + sourceSets.test.output
args = ['--plugin', 'pretty', '--glue', 'steps/rufs',
'src/test/resources/features', '--tags','#rufs']
}
}
}

You are not getting JUnit involved anywhere when running from Gradle. #RunWith is used by JUnit, and this in turn is what prompts Spring to get involved. When Cucumber is running as your suite, it's ignoring those annotations because it doesn't understand them.
You'll need to use JUnit as your suite (i.e. not run cucumber.api.cli.Main). You then have a problem because you need to use two "runners": Cucumber and Spring.
The way around this is JUnit's "rules" for one of the runners. Spring has a Rule, but as far as I can see Cucumber does not. In this case, use the Cucumber runner:
#RunWith(Cucumber.class)
in combination with Spring's rules, as described here: How to run JUnit SpringJUnit4ClassRunner with Parametrized?

Related

Spring Profiles in Cucumber Testing and Gradle

I have an automation test suite that is using Cucumber and Spring running with a Gradle build. I am facing an issue where depending on environment the property file used will be different. I know there is a way to use Profile annotations to specify ContextConfiguration but I can not find any resources on how to get started on this.
I believe I have to create a ProfileManager Class but I am not sure how to connect this to the #ContectConfiguration annotating my Cucumber Step Definitions and the Property Sources in my Configuration Class.
Here are some of my code samples.
StepDefintions.java
#CucumberContextConfiguration
#ContextConfiguration(classes = {ApplicationConfiguration.class, DynamoDBConfiguration.class})
#TestPropertySource("classpath:application-test-local.properties")
//#TestPropertySource("classpath:application-test.properties")
public class StepDefinition {
#Given("I set stuff up")
public void myGivenStep() {
app.assertTheThings()
#When("I do things")
public void myWhenStep() {
app.checksStuff();
}
.....
}
ApplicationConfiguraton.java
#Configuration
public class ApplicationConfiguration {
#Autowired
private Environment env;
.....
}
build.gradle
{
.....
task cucumber() {
dependsOn assemble, testClasses
doLast {
javaexec {
main='io.cucumber.core.cli.Main'
classpath=configurations.cucumberRuntime + sourceSets.main.output + sourceSets.test.output
def env = System.getProperty('testingENV')
println("Testing in " + env.toUpperCase() + ' Enviornment')
systemProperties = System.properties
def feature = ''
if (project.hasProperty('feature')) {
def arg1 = project.getProperty('feature')
feature = arg1
}
args = [
'--plugin', 'pretty',
'--plugin', 'json:target/cucumber-report.json',
'--glue', 'com.testautomation.cucumber',
"src/test/resources/com/testautomation/cucumber/feature/${feature}"
]
}
}
}
}
Basically I would like to use my testingENV system prop to define the profile and change which property source is being used without having to comment lines out everytime I am switching envs.

#MockBean injected correctly but with null value on test class

I am using tests with Cucumber and Spring Boot
#CucumberContextConfiguration
#ActiveProfiles(profiles = { "cucumber" })
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
#ExtendWith(SpringExtension.class)
public class FooTest {
#Autowired
BatchService batchService;
#MockBean
S3ClientService s3ClientService;
#MockBean
HttpClientService httpClientService;
#SpyBean
UndueService undueService;
#Given("^foo cucumber test$")
public void foo_cucumber_test() {
System.out.println("Foo Test");
}
}
When I run/debug my test with a break point on #Given method
I got this weird behavior, the #Mockbean/#SpyBean are correctly injected but in the test class its values are null !! and I can't run Mockito functions verify or when
But when I run a test without cucumber
#Test
void fooTest() {
System.out.println("Foo Test");
}
It works fine !! the values are not null
So, mock beans are created but not injected to the test suite. I guess you should put both #Autowired and #MockBean annotations.
Here is a similar question: Spring #MockBean not injected with Cucumber

Running JBehave with Junit 5 Jupiter

I'm trying to get some JUnit 4 based JBehave tests running on JUnit 5. In my project I have a single test class for all stories JBehaveTest.
When I run it as a JUnit 5 test JUnit doesn't see any tests. I modified the #Test annotations to their Jupiter equivalents, I changed the assertTrue and assertFalse to their equivalents, etc.
The JUnit 4 test is annotated with a #RunWith annotation, which in JUnit 5 should be a #ExtendWith annotation if I understood correctly. Unfortunately JBehave is not a JUnit 5 extension, so it won't compile.
Can JBehave be used with JUnit 5, and if so, how?
#RunWith(AnnotatedEmbedderRunner.class)
#UsingEmbedder(embedder = Embedder.class, verboseFailures = true, ignoreFailureInStories = false, generateViewAfterStories = true)
public class JBehaveTest implements Embeddable {
private Embedder embedder;
private DotStoryReporter dot = new DotStoryReporter();
private Stage primaryStage;
#Before
public void createStage() throws TimeoutException {
Locale locale = new Locale("fa", "IR");
Locale.setDefault(locale);
primaryStage = FxToolkit.registerPrimaryStage();
}
#Override
#Test
public void run() throws Throwable {
embedder.runStoriesAsPaths(new StoryFinder().findPaths("src/test/resources", Collections.singletonList("**/*.story"), Collections.<String>emptyList()));
}
#Override
public void useEmbedder(Embedder embedder) {
this.embedder = embedder;
MostUsefulConfiguration configuration = new MostUsefulConfiguration();
Steps steps = new Steps();
configuration.useStoryReporterBuilder(
new StoryReporterBuilder()
.withCodeLocation(CodeLocations.codeLocationFromClass(JBehaveTest.class))
.withDefaultFormats()
.withReporters(dot, new MyStoryReporter(new File("test"), steps))
.withFormats(Format.HTML, Format.TXT)
.withFailureTrace(true)
.withFailureTraceCompression(false));
configuration.useStepdocReporter(new DetailedStepReporter());
embedder.useStepsFactory(new InstanceStepsFactory(configuration, steps));
embedder.useConfiguration(configuration);
}
The Gradle test dependencies are:
testCompile 'org.junit.jupiter:junit-jupiter-api:5.2.0'
testCompile 'org.mockito:mockito-core:2.18.3'
testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
testRuntime 'org.junit.platform:junit-platform-launcher:1.2.0'
testCompile 'org.testfx:testfx-core:4.0.+'
testCompile 'org.testfx:testfx-junit5:4.0.+'
testCompile 'org.jbehave:jbehave-core:4.3.2'
testCompile 'de.codecentric:jbehave-junit-runner:1.2.0'

Cucumber Test a Spring Boot Application

Does anyone know where I can find a sample application where Cucumber is used to test a Spring Boot application through Gradle? I can run the tests fine starting the server on the cmd line and using my IDE, but I need to be able to run them all programmatically on the CI server. I saw the answer on here but that solution did not work for me, most likely because I have multiple step def files.
Here is my setup
build.grade (Mentioned in the other question)
testCompile ("org.springframework.boot:spring-boot-starter-test",
...
"info.cukes:cucumber-spring:${cucumberVersion}")
CucumberTest.java
#RunWith(Cucumber.class)
#CucumberOptions(format = "pretty", features = "src/test/resources")
public class CucumberTest{
}
AbstractSpringTest.java (Extended by all the StepDef files)
#SpringApplicationConfiguration(classes = Application.class)
#RunWith(SpringJUnit4ClassRunner.class)
#Ignore
public abstract class AbstractSpringTest
{ ... }
It's not doing the correct thing on start up because its 1. trying to initialize my step def files and 2. My application is not started and the cucumber tests cannot make a connection.
Thanks.
EDIT: Or if someone can tell me how to start and stop the application using gradle, that would be acceptable as well.
I have solved the issue with some help from this question.
Here is the repository with the answer:
https://github.com/jakehschwartz/spring-boot-cucumber-example
In short, the AbstractSpringTest class needs to have the following annotations:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = DemoApplication.class, loader = SpringApplicationContextLoader.class)
#WebAppConfiguration
#IntegrationTest
I had a similar symptom, my cucumber wouldn't start up the Spring context...
Turns out I had missed (one of) the following dependencies:
build.gradle
testCompile "info.cukes:cucumber-junit:1.2.4"
testCompile "info.cukes:cucumber-java:1.2.4"
testCompile "info.cukes:cucumber-spring:1.2.4"
StepDefs.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(
loader = SpringApplicationContextLoader.class,
classes = Application.class
)
#WebIntegrationTest(randomPort = true)
public class StepDefs {
#Value("${local.server.port}")
int port;
}
Update: SpringBoot 1.5.1
#ContextConfiguration(
loader = SpringBootContextLoader.class,
classes = Application.class
)
Further to #jakehschwartz, if you want the web app to start on a random available port, AbstractSpringTest needs:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = Application.class, loader = SpringApplicationContextLoader.class)
#WebIntegrationTest({"server.port=0"})
public abstract class AbstractSpringTest {
#Value("${local.server.port}")
protected int serverPort;
...}
I did something like this to get Spring to work with JUnit parameterized tests. It should be the same concept for Cucumber, but I haven't tried it. I was using XML configuration, so that might make a difference.
RunWithSpringJUnit4
public abstract class RunWithSpringJUnit4 {
private TestContextManager testContextManager;
public RunWithSpringJUnit4() {
try {
this.testContextManager = new TestContextManager(getClass());
this.testContextManager.prepareTestInstance(this);
} catch (Exception e) {
e.printStackTrace();
}
}
}
CucumberTest
#RunWith(Cucumber.class)
#CucumberOptions(format = "pretty", features = "src/test/resources")
public class CucumberTest extends RunWithSpringJUnit4 {
}
First, you'll need to ensure that you have applied spring-boot in gradle. Invoke gradle build which will produce a runnable jar. Instead of having your manifest call for the Spring class as your main, have a wrapper that starts it in a thread, waits for it to settle down and runs Cucumber:
#RunWith(Cucumber.class)
public class LucasePsCucumberTest implements Runnable {
public static void main(String[] args) {
Thread t = new Thread(this);
t.start();
// wait for t
cucumber.api.cli.Main(null);
}
}

Infinitest fails but Maven works

I have Sprint Tool Suite 3.3 and the latest version of Infinitest installed. According to Infinitest, many of my classes have errors, but yet Maven builds just fine. Here is an example of some errors that the Problems tab in STS show:
InvalidDataAccessResourceUsageException (Table "ADDRESSTYPEREF" not found; SQL statement:...SeedAddressTypes.java /... line 34 Infinitest Test Failure
AssertionFailure (null id in com..model.base.Menu entry (don't flush the Session after an exception occurs)) in TestMenuBuilderIT.sortByTopMenu TestMenuBuilderIT.java
All the tests that show an error are integration that use Java Config for the EmbeddedDatabase:
public class TestMenuBuilderIT extends BaseItegration {
#Autowired
private MenuRepository menuRepository;
#Test
public void sortByTopMenu() {
List<Menu> testMenu = menuRepository.findAll(); <== offending line
...
}
And the configuration class:
#RunWith( SpringJUnit4ClassRunner.class )
#ContextConfiguration( loader = AnnotationConfigContextLoader.class, classes = { JpaConfig.class } )
public abstract class BaseItegration {
..
}
#Configuration
#EnableTransactionManagement
#ComponentScan( basePackages = { ...} )
#ImportResource( { "classpath:applicationContext.xml"} )
public class JpaConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder().setType( EmbeddedDatabaseType.H2 ).setName( "testdb" )
.addScript( "classpath:embeddedDatabase.sql" ).build();
}
I don't see why this would work fine in Maven, but Infinitest has these DB related errors. I could not find any documentation saying that JavaConfig wouldn't work with Infinitest. I am able to right click and run each test "As A Unit Test" successfully.
Does anyone know what might cause this?

Categories