AutoWiring steps with Spring Cucumber Serenity - java

I'm failing miserably to auto wire some steps.
To illustrate the point, I made a small sample project on github
https://github.com/lpicquet/serenity-cucumber-spring
I am trying to autowire steps so that I can share data between them but the test is currently failing. Anyone can help?

The issue is that you are using a different Runner. Generally people use the SpringRunner.class which handles the ability to create the test context etc.
Construct a new SpringRunner and initialize a TestContextManager to provide Spring testing functionality to standard JUnit 4 tests.
To use a different runner along with spring functionality you can use a combination of a ClassRule and a Rule
#ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
#Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
SpringClassRule is a custom JUnit TestRule that supports class-level features of the Spring TestContext Framework in standard JUnit tests by means of the TestContextManager and associated support classes and annotations.
In contrast to the SpringJUnit4ClassRunner, Spring's rule-based JUnit support has the advantage that it is independent of any Runner and can therefore be combined with existing alternative runners like JUnit's Parameterized or third-party runners such as the MockitoJUnitRunner.
In order to achieve the same functionality as the SpringJUnit4ClassRunner, however, a SpringClassRule must be combined with a SpringMethodRule, since SpringClassRule only supports the class-level features of the SpringJUnit4ClassRunner.
Without these there is no ability to Autowire within your dependant classes etc.
I've added a PR to your project with passing tests.

Related

What is the difference between #ExtendWith(SpringExtension.class) and #ExtendWith(MockitoExtension.class)?

I was using #RunWith(MockitoJUnitRunner.class) for my junit test with mockito. But now I am working with spring-boot and JUnit 5.
What's the difference between the two annotations ?
Can I use only #ExtendWith(SpringExtension.class) to mock my objects ?
When involving Spring:
If you want to use Spring test framework features in your tests like for example #MockBean, then you have to use #ExtendWith(SpringExtension.class). It replaces the deprecated JUnit4 #RunWith(SpringJUnit4ClassRunner.class)
When NOT involving Spring:
If you just want to involve Mockito and don't have to involve Spring, for example, when you just want to use the #Mock / #InjectMocks annotations, then you want to use #ExtendWith(MockitoExtension.class), as it doesn't load in a bunch of unneeded Spring stuff. It replaces the deprecated JUnit4 #RunWith(MockitoJUnitRunner.class).
To answer your question:
Yes you can just use #ExtendWith(SpringExtension.class), but if you're not involving Spring test framework features in your tests, then you probably want to just use #ExtendWith(MockitoExtension.class).

TestNG vs Junit vs Mockito?

I am having difficulty understanding the difference between these 3. Aren't all of these testing frameworks, and not libraries? If so, how is it that we are able to use these in combination? Shouldn't we be able to only use one testing framework, since the framework dictates the flow of control of code unlike in the case of libraries where we call the library code from our code. How can 2 independent frameworks work together on the same piece of code? I've observed that Mockito is used in conjunction with TestNG a lot. Isn't TestNG sufficient for most testing scenarios?
Both Testng and Junit are Testing framework used for Unit Testing. TestNG is similar to JUnit. Few more functionalities are added to it that makes TestNG more powerful than JUnit.
Annotations
Both JUnit and TestNG uses annotations and almost all the annotations looks similar.
TestNG uses #BeforeMethod ,#AfterMethod similar to #Before ,#After in JUnit4.
.........................
Mockito is a java based mocking framework, used in conjunction with other testing frameworks such as JUnit and TestNG.
It internally uses Java Reflection API and allows to create objects of a service. A mock object returns a dummy data and avoids external dependencies. It simplifies the development of tests by mocking external dependencies and apply the mocks into the code under test.
Summary
So as its name suggest Mockito is used for mocking the data or fake data which is act as real object to test, its acts like an stub or driver while still we need junit or testng with it. while Junit and TestNG is a unit testing framework of java
Explanation Tutorial
https://www.youtube.com/watch?v=eILy4p99ac8
Article on Mockito
https://www.journaldev.com/21816/mockito-tutorial

What's the difference between #RunWith(MockitoJUnitRunner.class) and #RunWith(SpringJUnit4ClassRunner.class)? When to use it appropriately?

What's the difference between #RunWith(MockitoJUnitRunner.class) and #RunWith(SpringJUnit4ClassRunner.class)? When to use it appropriately?
MockitoJUnitRunner
specific for use with the Mockito test framework
the Mockito framework helps with mocking dependencies when you want to focus your tests on a single class and avoid invoking methods on dependencies (instead invokes a mock/dummy that is easily configured).
Above is what mockito is used for, but for more on this runner specifically - from the docs: "keeps tests clean and improves debugging experience". "Runner is completely optional - there are other ways you can get #Mock working". Source - https://static.javadoc.io/org.mockito/mockito-core/2.6.8/org/mockito/junit/MockitoJUnitRunner.html
SpringJunit4ClassRunner
specific for use with the spring framework
used for integration tests when it is required to load the spring context (create spring beans, perform dependency injection, etc).
In integration tests you may not do as much mocking of dependencies but you can do both in the same test.
Integration tests are useful when you would like to test loading the spring context or perhaps test from the service/high level all the way down to lower levels like data access with a single test.
In some cases you may want to use both - like an integration test where you would also like to mock some dependencies (perhaps they make remote calls). Unfortunately you can't use two #RunWiths but this is a good post about that - Multiple RunWith Statements in jUnit

Need to use dependency injection in unit tests - should I use junit or testng?

We are looking at how to use dependency injection into unit tests (using JSR-330 syntax but without explicitly specifying the engine in the basic tests if that matters), and we have used junit 4 so far and been very pleased with it, but it appears that it is not designed for dependency injection in the tests.
Question is, whether junit is well suited for tests to be run in a dependency injection context, or if I should just switch to TestNG?
Just to clarify: We are trying to be DI-engine agnostic, and currently looking at dagger.
I would appreciate if opinions were backed up with fact, thanks.
Assuming you are using Spring framework
You can annotate your Junit test classes like this:
#RunWith( SpringJUnit4ClassRunner.class )
#ContextConfiguration( "classpath:appTest-context.xml" )
public class AppServiceTest{
...
...
}
And inside appTest-context.xml have your regular Spring config stuff for injecting all the dependencies.
Junit have #RunWith annotation, check org.springframework.test.context.junit4.SpringJUnit4ClassRunner
as example of implementation DI in Junit tests
I am not sure about the JUnit (but by seeing other answers seems like it is also possible with JUnit) but in our application we used TestNG for running the test cases and we were successfully able to inject the dependencies.

spring with testNG without subclassing

is there any way to use testNG and spring without subclassing or copying half of AbstractTestNGSpringContextTests? is there anything simple like junit's #RunWith?
According to the Spring documentation, it doesn't look like it provides a TestNG test runner out of the box:
In addition to generic testing infrastructure, the TestContext framework provides explicit support for JUnit 3.8.2, JUnit 4.5+, and TestNG 5.10 in the form of abstract support classes. For JUnit 4.5+, the framework also provides a custom Runner that allows one to write test classes that are not required to extend a particular class hierarchy.
I suppose you could try to write a your own custom TestNG test runner that could do something similar.

Categories