I want to use parameterized JUnit tests on a play! framework (1.2.5) application.
This is my very simple test example:
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import play.test.FunctionalTest;
#RunWith(Parameterized.class)
public class ParameterizedExampleTest extends FunctionalTest {
private int i;
#Parameters
public static List<Object[]> parameters() {
return Arrays.asList(new Object[][] {{1},{2},{3}});
}
public ParameterizedExampleTest(int i) {
this.i = i;
}
#Test
public void someTest() {
System.out.println("i is " + i);
}
}
When I run the test, I get an IllegalArgumentException telling me "Test class can only have one constructor". I perfectly agree with that as FunctionalTest extends BaseTest which has a #RunWith(PlayJUnitRunner.class) annotation and the PlayJUnitRunner has a constructor.
Any help welcome!
I found a rather nice solution:
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import play.test.FunctionalTest;
#RunWith(Parameterized.class)
public class ParameterizedExampleTest extends FunctionalTest {
#Parameter(0)
public int i;
#Parameters
public static List<Object[]> parameters() {
return Arrays.asList(new Object[][] {{1},{2},{3}});
}
#Test
public void someTest() {
System.out.println("i is " + i);
}
}
You have to mark the parameters with the #Parameter(...) Annotation and the number of the parameter in the parameters array. No constructor is needed hence it runs smoothly with play.
Drawback: You will need JUnit 4.11 as this feature is not implemented in 4.10 which is what play (1.2.5) comes with.
Related
It is a very strange issue. Removing the JSON in TestUtil or the executorService/submit will make the following code working:
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ATest {
#BeforeAll
public static void setup(TestInfo test) throws Exception {
}
#Test
void testThis(){
int numThreads = 1;
ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
threadPool.submit(() -> {
TestUtils.doSomething();
});
}
}
Here is the class with the ObjectMapper>
import com.fasterxml.jackson.databind.ObjectMapper;
public class TestUtils {
private static final ObjectMapper JSON;
static {
JSON = new ObjectMapper();
}
public static void doSomething() {
System.out.println("entered the method");
}
}
Currently, the method doSomething() would not be entered at all.
This issue will be resoved if we trigger the Junit test from Maven or if run it from a static main method.
I am trying to build Spring-boot CRUD application with Hibernate and REST -API.However when I try to run the app everything is working fine but console is displaying the following error
java.lang.NullPointerException: null
at io.javabrains.EmployerController.getAllEmployers(EmployerController.java:20) ~[classes/:na]
I tried to change the value however it didnt work
EmployerService.java
package io.javabrains;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import io.javabrains.Entity.Employer;
#Service
public class EmployerService {
private Repository repository;
public List<Employer>getAllEmployers(){
List<Employer>employers = new ArrayList<>();
repository.findAll()
.forEach(employers::add);
return employers;
}
public void addEmployer(Employer employer) {
repository.save(employer);
}
}
EmployerController.java
package io.javabrains;
import java.util.List;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import io.javabrains.Entity.Employer;
#RestController
public class EmployerController {
private EmployerService service;
#RequestMapping("/employer")
public List<Employer>getAllEmployers()
{
return service.getAllEmployers();
}
/*
* #RequestMapping("/employer/{id}") public Employer getEmployer(#PathVariable
* int id) { return service.getEmployer(id); }
*/
#RequestMapping(method=RequestMethod.POST,value="/employer/create")
public void addEmployer(#RequestBody Employer employer) {
service.addEmployer(employer);
}
}
....
On the analysis of the code snippet given, the null pointer exception occurred since your code doesn't ask the spring dependency injector to inject EmployerService as a dependency to EmployerController, so it doesn't inject the EmployerService bean class to the reference private EmployerService employerService; thus it is null in EmployerController. You can ask Spring Dependency Injector to inject dependency by adding #Autowire annotation private EmployerService service; refence in EmployerController
Update your EmployerService to the following will work
package io.javabrains;
import java.util.List;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import io.javabrains.Entity.Employer;
#RestController
public class EmployerController {
//UPDATE : Autowiring
#Autowired
private EmployerService employerService;
#RequestMapping("/employer")
public List < Employer > getAllEmployers() {
return service.getAllEmployers();
}
/*
* #RequestMapping("/employer/{id}") public Employer getEmployer(#PathVariable
* int id) { return employerService.getEmployer(id); }
*/
#RequestMapping(method = RequestMethod.POST, value = "/employer/create")
public void addEmployer(#RequestBody Employer employer) {
employerService.addEmployer(employer);
}
}
And Also, the same issue would occur in Service when trying to access repository.
Update EmployeeService.java code include #autorwired logic:
package io.javabrains;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import io.javabrains.Entity.Employer;
#Service
public class EmployerService {
#Autowired
private Repository repository;
public List<Employer>getAllEmployers(){
List<Employer>employers = new ArrayList<>();
repository.findAll()
.forEach(employers::add);
return employers;
}
public void addEmployer(Employer employer) {
repository.save(employer);
}
}
private EmployerService employerService;
This mean you have created a reference variable of EmployerService not an object of EmployerService. Which can be done by using a new keyword. But as you know Spring Container uses DI(Dependency Injection) to manage a beans(an object, in above case object of EmployerService). So the object instantiation and whole lifecycle of an object is managed by the spring. For this we have to tell that the this object should be managed by the spring which is done by using #Autowired annotation.
You need to get object of repository before using, for that add #Autowired on
private Repository repository;
in your EmployerService class.
#Autowired is definitely the solution.
But your service class, if you ask for your REPOSITORY, you should put there too.
So in my problem, the solution was
#Autowired
private ProductService productService;
And
#Autowired
ProductRepository productRepository;
there was a line inside a method that was throwing this NullpointerException then later on I put that line in the if statement and it worked for me seamlessly.
example:
if (user != null) { application.setEmailaddress(user.getEmail());}
I'm using HK2 for dependency injection and want to replace a Singleton Object with a Mockito-mock in the context of a JUnit-Test.
The simplest setting would be as follows:
import javax.inject.Inject;
import org.jvnet.hk2.annotations.Service;
#Service
public class A {
#Inject
private B b;
public String test() {
return b.toString();
}
}
#Service
public class B {
public String toString()
{
return "B";
}
}
whereas the JUnit-Test stub is as follows:
import static org.junit.Assert.*;
import javax.inject.Inject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.jvnet.hk2.testing.junit.HK2Runner;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
public class MockTest extends HK2Runner {
private B bMock = Mockito.mock(B.class);
#Inject
private A a;
#Test
public void test() {
Mockito.when(bMock.toString()).thenReturn("Mock");
assertEquals("Mocking worked", "Mock", a.test());
}
}
I want the Mock for B to be injected into A and not the real Object. How can I configure HK2 globally, such that for every instance of B the mock is used?
I already know that I could inject B locally into A by using injection via constructor.
Have you considered using a #Stub of B rather than a Mock?. To do that you can add #Contract onto the implementation of B:
#Service #Contract
public class B {
public String toString()
{
return "B";
}
}
and rather than using the mock use a #Stub:
public class MockTest extends HK2Runner {
#Inject
private A a;
#Test
public void test() {
assertEquals("Mocking worked", "Mock", a.test());
}
#Stub #Rank(1)
public static abstract class BStub extends B {
public String toString() {
return "Mock";
}
}
}
In order for this to work the hk2-metadata-generator should be in the classpath of your test during compilation so it can generate the stub. You put #Rank(1) on the stub to ensure it gets picked over the original B class.
Hope this helps!
I'm new to JUnit and was learning the various annotations. The code below however is giving me output that seems wrong
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
public class SampleTest {
#BeforeClass
public static void beforeClass() {
System.out.println("Before Class"); }
#AfterClass
public static void afterClass() {
System.out.println("After Class"); }
#Before
public void before() {
System.out.println("Before"); }
#After
public void after() {
System.out.println("After"); }
#Test
public void testAreFirstAndLastNCharactersTheSame() {
System.out.println("testAreFirstAndLastNCharactersTheSame");}
#Test
public void testTruncateAinFirstNPositions() {
System.out.println("testTruncateAinFirstNPositions"); }
}
The output I get is
Before
testTruncateAinFirstNPositions
After
Before
testAreFirstAndLastNCharactersTheSame
After
Before Class
After Class
This seems wrong as the "Before Class" print should be first. Am I doing something wrong? My Junit version is 4.12. I ran the above piece of code on Intellij.
The actual output screenshot is below
I implemented a runner class A.class inherited from BlockJUnit4ClassRunner so that I can annotate tests with #RunWith(A.class). At the same time, sb. else annotate the tests with RunWith(Parameterized.class). It is obvious we cannot use two #RunWith at the same time.
How to solve this problem? or how to merge these two #RunWith?
I believe this does what you want:
package so.junit.runner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.model.InitializationError;
import org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters;
import org.junit.runners.parameterized.ParametersRunnerFactory;
import org.junit.runners.parameterized.TestWithParameters;
import java.util.Arrays;
#RunWith(Parameterized.class)
#Parameterized.UseParametersRunnerFactory(CustomParameterizedTest.RunnerFactory.class)
public class CustomParameterizedTest {
#Parameterized.Parameters
public static Iterable<Integer> data() {
return Arrays.asList(new Integer[]{1, 2, 3});
}
private int i;
public CustomParameterizedTest(int i) {
this.i = i;
}
#Test
public void test() {
System.out.println(i);
}
public static class RunnerFactory implements ParametersRunnerFactory {
#Override
public org.junit.runner.Runner createRunnerForTestWithParameters(TestWithParameters test) throws InitializationError {
return new A(test);
}
}
public static class A extends BlockJUnit4ClassRunnerWithParameters {
private final Object[] parameters;
public A(TestWithParameters test) throws InitializationError {
super(test);
parameters = test.getParameters().toArray(new Object[test.getParameters().size()]);
}
#Override
public Object createTest() throws Exception {
return getTestClass().getOnlyConstructor().newInstance(parameters);
}
}
}
Based on the Javadocs in the JUnit Parameterized class, this is how they expect you to create a custom test runner that supports parameterization.
UPDATE
Updated to name the custom runner A