JUnit 5.6.0 with static autoincrement field initializes it twice - junit

I have a strange issue with JUnit 5.6.0 that I don't recall it was there before.
class Student {
private static int autoInc = 0;
private int regNum = 0;
public Student(...) {
regNum = autoInc++;
}
public int getRegNum() { return regNum; }
//...
}
and the unit test
public class StudentTest {
private final Student instance = new Student(...);
#BeforeEach
public void setUp() {}
#AfterEach
public void tearDown() {}
#DisplayName("getRegNum")
#Test
public void testGetRegNum() {
assertEquals(1, instance.getRegNum());
}
}
When I execute it, instead of having the test pass, it fails because the instance's regNum field has value 2 instead of 1.
After debugging, I realized that a NativeConstructorAccessorImpl is being called twice who creates 2 instances of Student which explains why the static fields has been called two times.
Why is this and how can I avoid it? This is something internal to the JUnit framework but it affects my unit test case. Of course I don't want to pollute my class with a setter or a public static field.

Related

Mocking an injected object in a method return and UnsupportedOperationException method

I have a class that returns an injected object using Mockito. Everytime I test it, it returns a bull. How would I properly test it to return the correct object?
My class to test:
#Component
public class CarImpl {
#Inject
private Engine v6EngineImpl;
public Engine getEngine() {
return v6EngineImpl;
}
public Exhaust getExhaust() {
throw new UnsupportedOperationException("unsupported");
}
}
Tests:
#RunWith(MockitoJUnitRunner.class)
public class CarTest {
#InjectMocks
private CarImpl carImpl;
#Mock
private Engine v6EngineImpl;
#Test
public void testGetEngine(){
Engine v6EngineImpl = mock(V6EngineImpl.class);
Engine engine = carImpl.getEngine();
// always returns a bull no matter what, how to mock inject.
//return object correctly?
Assert.assertNotNull(engine);
}
#Test
public void testGetExhaust() {
// how to test thrown exception?
}
}
Thanks, I am not too familiar thanks
Try this:
#RunWith(MockitoJUnitRunner.class)
public class CarTest {
#InjectMocks
private CarImpl carImpl;
#Mock
private Engine v6EngineImpl;
#Test
public void testGetEngine(){
Engine engine = carImpl.getEngine();
//engine is the mock injected to CarImpl
Assert.assertNotNull(engine);
Assert.assertSame(engine,v6EngineImpl);
}
#Test(expected=UnsupportedOperationException.class)
public void testGetExhaust() {
carImpl.getExhaust();
}
}

How to mock a void method with no arguments?

For Example:
Class A{
string s = null;
public void method(){
s="Sample String";
}
}
I have a void method with similar scenario. How can I test such void method?
With void methods you should test the interaction with its dependent objects within the void method. I think a void method with no argument is rarely useful to test (but if you have a valid use case, please add it to your question). I provided you a simple example for a method with an argument but void as a return type:
public class A {
private DatabaseService db;
private PaymentService payment;
// constructor
public void doFoo() {
if(n < 2) {
db.updateDatabase();
} else {
payment.payBill();
}
}
}
And the unit test for this can look like the following
#RunWith(MockitoJUnitRunner.class)
public class ATest {
#Mock
DatabaseService db;
#Mock
PaymentService payment;
#Test
public void testDoFooWithNGreaterTwo() {
A cut = new A(db, payment); // cut -> class under test
cut.doFoo(3);
verify(payment).payBill(); // verify that payment was called
}
#Test
public void testDoFooWithNLessThanTwo() {
A cut = new A(db, payment); // cut -> class under test
cut.doFoo(1);
verify(db).updateDatabase(); // verify that db was called
}
}

Unit Test class not running properly - Mocking Interfaces

I have a simple Controller class like below:-
#RestController
public class CrawlerAppController {
private static final Logger LOGGER = LoggerFactory.getLogger(CrawlerAppController.class);
#Autowired
private CrawlerServiceInterface crawlerService;
/* The response time of the crawling operation is directly proportional to the no of pages
* we want to crawl. Keeping a default value of 10 so we can view the results quicker.
* author: Arunava Paul
*/
#RequestMapping(value = "/crawl", method = { RequestMethod.GET })
public Object crawlUrl(#RequestParam(value = "URL") String URL,
#RequestParam(value = "max", defaultValue = "10") int maxPages) throws Exception {
if(!URL.startsWith("https://"))
URL="https://"+URL;
LOGGER.info("Request Received. Domain "+URL+" Pages to be Crawled "+maxPages);
return crawlerService.crawlService(URL, maxPages);
}
}
I have written a Junit class like below:-
#RunWith(PowerMockRunner.class)
public class CrawlerAppControllerTest {
Object obj=new Object();
#Spy
#InjectMocks
private CrawlerServiceInterface crawlerService = Mockito.any(CrawlerService.class);
#InjectMocks
CrawlerAppController appController = new CrawlerAppController();
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testController() throws Exception {
when(crawlerService.crawlService("https://vogella.com", 20)).thenReturn(obj);
assertEquals(appController.crawlUrl("vogella.com",20), obj);
}
}
It's always going into the Service class and the when statement is not running.
Can someone please advise what have I done wrong. Below error comes if I run Junit.
You should declare crawlerService like this:
#Mock
private CrawlerServiceInterface crawlerService;
The declaration of crawlerService in the test class should be:
#Mock
private CrawlerServiceInterface crawlerService;

How to get a static final property from a property file with spring boot

I've a spring boot project working on mysql DB. To encrypt some column I used the mysql function aes_encrypt, aes_decrypt and I stored my secret_key in a property file. Now to make some query on db I've to use in the crudrepository some native query like this.
#Query(value = "select * from a_table at where AES_DECRYPT(at.column1, +StaticClass.KEY+)= 'ABC'", nativeQuery = true)
public List<A>findByParameter();
I get this error "The value for annotation attribute Query.value must be a constant expression"
But the property KEY is already a FINAL property instantiate in this way
public class StaticClass {
static {
Properties prop = new Properties();
InputStream input;
try {
input = new FileInputStream("application.properties");
prop.load(input);
} catch (IOException e) {
logger.error("Error");
}
if(prop.getProperty("property1")==null) {
logger.error("property not found");
}
KEY=prop.getProperty("property1", "");
}
public static final String KEY;
One solution is to store the key in the code, but i need to keep the key in a property file. How can solve this problem?
Updated 1
I tried also in this way
public class StaticClass {
#Value(value="property1")
public static final String KEY;
}
You can create for this constants like below.
public enum Foo {
FOO("app.foo"), FOO_BAR("app.foo.bar");
private Environment environment;
private final String propertyKey;
Foo(String propertyKey) {
this.propertyKey = propertyKey;
}
public String getValue() {
return environment.getProperty(propertyKey);
}
private void setEnvironment(Environment environment) {
this.environment = environment;
}
#Component
private static class EnvironmentInjector {
#Autowired
private Environment environment;
#PostConstruct
private void postConstruct() {
for (Foo fT : EnumSet.allOf(Foo.class))
fT.setEnvironment(environment);
}
}
}
then you can use like this :
Foo.FOO.getValue()
#Query(value = "select * from a_table at where AES_DECRYPT(at.column1, +Foo.FOO.getValue()+)= 'ABC'", nativeQuery = true)
public List<A>findByParameter();

Performing a custom action when a given mocked void method is called

I would like to be able for Mockito to perform a custom action when a given void method is called.
Say I have the following code:
#Autowired
private ProfileService profileService;
#Autowired
private ProfileDao profileDao;
private List<Profile> profiles;
#Before
public void setup() {
Mockito.when(profileDao.findAll()).thenReturn(profiles);
Mockito.when(profileDao.persist(any(Profile.class))).thenAddProfileToAboveList...
}
#Configuration
public static class testConfiguration {
#Bean
public ProfileDao ProfileDao() {
return mock(ProfileDao.class);
}
}
Say I want to add a Profile instance to the profiles list. Can Mockito do that? If so how?
Use Mockito.doAnswer.
doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) {
// make the changes you need here
}})
.when(mock).someMethod();