JUnit5: Running a single "instance" of parameterized test - maven

Let's say we have a parameterized test exampleTest in JUnit5:
public class ExampleTestClass {
#ParameterizedTest(name = "exampleTest[{0}]")
#MethodSource("StringParams#getStrings")
void exampleTest(String input) {
// ...
}
}
public class StringParams {
static Stream<String> getStrings() {
return Stream.of("a", "b", "c");
}
}
Is there any way to execute only one instantiation of exampleTest in JUnit5? In JUnit4+Maven+Surefire, the following would work:
mvn test -Dtest="ExampleTestClass#exampleTest[a]"
But it doesn't seem to work with JUnit5+Maven+Surefire. Is it because the test names that get into the test selecting process (which tests will be executed and which are going to be omitted) are different from the one specified in #ParameterizedTest(name = "exampleTest[{0}])?

I haven't tried it but the doc of surefire:test#test reads:
<test>
[...] Since 2.7.3, you can execute a limited number of methods in the test by adding #myMethod or #my*ethod. For example, -Dtest=MyTest#myMethod. This is supported for junit 4.x and TestNg.
Since 2.19 a complex syntax is supported in one parameter (JUnit 4, JUnit 4.7+, TestNG):
(Emphases by me.)

Related

Testing Gradle task that uses javaexec()

Suppose I have a custom Gradle task that uses ExecOperations.javaexec() in its code:
public class MyTask extends DefaultTask {
private final ExecOperations execOps
#Inject
public MyTask(ExecOperations execOps) {
this.execOps = execOps;
}
#TaskAction
public void run() {
ExecResult result = execOps.javaexec(spec -> {
// classpath is set to some jar with a main class
spec.classpath(...);
spec.args(...);
});
// Do more stuff with result
}
}
The issue I have is that I am not sure how I can create a Spock test fixture for it to validate that the jar is being run with the correct arguments without actually running the jar itself. (The jar makes remote calls, for example, which I want to avoid).
It seems like the only plausible way forward is to potentially find a way to expose the ExecOperations for testing and possibly replace it with a stub, along with turning the Action<JavaExecSpec> from a mere lambda to something more substantial. Any ideas would be appreciated.

Spring profiles on integration tests class

we have selenium tests which are ran by java test class.
On local environment everything is ok, but I want to switch off those tests when run on jenkins.
So I use:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebIntegrationTest("server.port=1234")
#Profile("!jenkins")
#ActiveProfiles("integrationtests")
public class LoginAndEditProfileSeleniumTest {
...
What works:
running mvn clean test run all tests locally, with integrationtests profile active. I dont want to pass any additional parameter.
What I want to achieve:
running mvn clean test -Dspring.profiles.active=jenkins switch off this test.
Can I merge somehow profile passed by parameter, ActiveProfile annotation and take Profile annotation into consideration? :)
//update:
Its possible to use class extending ActiveProfilesResolver:
public class ActiveProfileResolver implements ActiveProfilesResolver {
#Override
public String[] resolve(Class<?> testClass) {
final String profileFromConsole = System.getProperty("spring.profiles.active");
List<String> activeProfiles = new ArrayList<>();
activeProfiles.add("integrationtests");
if("jenkins".contains(profileFromConsole)){
activeProfiles.add("jenkins");
}
return activeProfiles.toArray(new String[activeProfiles.size()]);
}
}
but it seems to not to cooperate with #Profile anyway ( jenkins profile is active but test is still running ) .
#Profile has zero affect on test classes. Thus, you should simply remove that annotation.
If you want to enable a test class only if a given system property is present with a specific value, you could use #IfProfileValue.
However, in your scenario, you want to disable a test class if a given system property is present with a specific value (i.e., if spring.profiles.active contains jenkins).
Instead of implementing a custom ActiveProfileResolver, a more elegant solution would be to use a JUnit assumption to cause the entire test class to be ignored if the assumption fails.
This should work nicely for you:
import static org.junit.Assume.*;
// ...
#BeforeClass
public static void disableTestsOnCiServer() {
String profilesFromConsole = System.getProperty("spring.profiles.active", "");
assumeFalse(profilesFromConsole.contains("jenkins"));
}
Regards,
Sam (author of the Spring TestContext Framework)

Multiple runwith for a junit test class

Does any one know how to tackle this.
#RunWith(SpringJUnit4ClassRunner.class)
#RunWith(Parametrized.class)
#ContextConfiguration("/META-INF/blah-spring-test.xml")
public class BlahTest
..
so i want to have a spring nature test and at the same time want to have it parameterized to avoid code duplication ...
You can't use two runners as it noted in the commented post. You should use the Parameterized runner as use Spring's TestContextManager to load the Spring context.
#Before
public void before() throws Exception {
new TestContextManager(getClass()).prepareTestInstance(this);
}
As of Spring Framework 4.2, JUnit-based integration tests can now be executed with JUnit rules instead of the SpringJUnit4ClassRunner. This allows Spring-based integration tests to be run with alternative runners like JUnit’s Parameterized or third-party runners such as the MockitoJUnitRunner. See more details on spring doc.
Building upon John B's answer using TestContextManager, one can also call beforeTestMethod() and afterTestMethod() on it to better simulate SpringJUnit4ClassRunner's behaviour (for instance loading database with #Sql).
These methods require a Method parameter, so one can for instance take advantage of JUnit4's TestName rule to get the current test method's name and then retrieving it by reflection.
private static TestContextManager springTestContext
= new TestContextManager(BlahTest.class);
#Rule
public TestName testName = new TestName();
#Before
public void before() throws Exception {
springTestContext.prepareTestInstance(this);
springTestContext.beforeTestMethod(this,
getClass().getMethod(testName.getMethodName()));
}
#After
public void after() throws Exception {
springTestContext.afterTestMethod(this,
getClass().getMethod(testName.getMethodName()), null);
}

Change locale for JUnit tests via Spring context

All tests are launched by gradle.
I'd like to define the locale for all JUnit tests on a project. At first I thought about the following way:
public class TestCases {
static Locale defaultLocale = Locale.getDefault();
#BeforeClass
public static void setDefaultLocale() {
Locale.setDefault(Locale.UK);
}
// here goes bunch of tests
// ...
#AfterClass
public static void restoreLocale() {
Locale.setDefault(defaultLocale);
}
}
But it is too cumbersome, as I have hundreds of files to be changed.
I found also that running single test with -Duser.language=en parameter (I use Intellij) will do the job. But I am not able to change gradle scripts in order to provide this solution.
Is there any way to define Locale for JUnit tests via Spring context? Or maybe there is an other better way? Thanks.
One way to achieve this would be to add a test lifecycle hook that is fired before your suite is executed.
test.beforeSuite { TestDescriptor suite ->
System.setProperty('user.language', 'en')
}

How to priortized the test cases in maven run?

I have 3 test cases i.e. 1 2 3. How will i give priority as 2 1 3 while executing maven command.
I assume you want to do it because you need some prerequisition prior the test can be run. You can do it by #Before Annotation prior the actual testcase, or you can call other tests from the test method.
Say, testClient() test will test and verify that new client can be added to the system. Then you can do this:
#Test
public void testWithdrawal(){
testClient(); // i need client existing before the test can be run
// ... do something else
}
In that case you have assured that prerequisites are fullfilled and dont have to worry much about the testcases order
EDIT
I think I understand your needs, because I am in quite similar situation. How I solved it:
For create I have special class, which can create me a data and return needed data. So, i have something like:
#Test
public void testShare(){
CreateTests create = new CreateTests; //This will just initialize the object
create.testCreate(); // this method can contain steps needed to create
String justCreatedEntity = create.getEntity(); // just example how you can use the just created entity in further tests
}
And my class to solve the create is something like this
public class CreateTests{
private static String entity; //static because i dont want it to be flushed when test ends
public void testCreate() throws Exception{
WebDriverBackedSelenium selenium = new WebDriverBackedSelenium(driver, "baseURL");
selenium.... // All the selenium stuff
setEntity(selenium.getText("id=mainForm.createdentity"));
}
public void setEntity(String ent){
this.entity = ent;
}
public String getEntity(){
return entity;
}
Its just an outline - but basically, I have these "crucial" entities as standalone objects, called by the test class. Inside test, i verify everything throgh getters. Like:
Assert.assertNotNull(create.getAuctionID(),"New Entity is NULL!" );
You can run mvn test with options to specify a single test, or multiple tests. The order they are run in is the order specified on the command line.
Reference is here: http://maven.apache.org/plugins/maven-surefire-plugin/examples/single-test.html
Note that Java suggests that the good unit testing practice of tests not requiring to be run in order and test to not rely on each other:
http://java.sun.com/developer/Books/javaprogramming/ant/ant_chap04.pdf

Resources