how to use System.getenv in Junit PowerMockito - java

I'm able to mock the System.getenv value from Junit but when I execute the test case - in my service class System.getevn value coming as null. Not sure what I'm doing wrong here. Please find my test service class and junit class.
Can some please help me to fix this issue - why the value is not setting in my actual service class?
TestService.java
public class TestService {
public TestService() throws Exception {
loadTestMethod();
}
private void loadTestMethod() {
System.out.println("Environment vairlable : " + System.getenv("my_key_name"));
System.setProperty("app.key", System.getenv("my_key_name"));
}
}
TestServiceTest.java
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(value = { System.class })
#PowerMockIgnore("javax.management.*")
public class TestServiceTest {
#Mock
TestService testService;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getenv("my_key_name")).thenReturn("Testing");
System.out.println("Junit Environment vairlable : " + System.getenv("my_key_name"));
testService = new TestService();
}
#Test
public void myServiceTest() {
}
}

Just because PowerMockito allows us to mock static does not mean that we should.
Your classes are dependent on static implementation concerns that make unit testing in isolation, in most cases, difficult.
Consider following the Explicit Dependency Principle
Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.
Create an abstraction of the desired functionality
public interface SystemWrapper {
//The "standard" output stream
PrintStream out;
//Gets the value of the specified environment variable
string getenv(string name);
//Sets the system property indicated by the specified key.
string setProperty(String key, String value);
}
The implementation will encapsulate the actual calls to the static system class
public class SystemWrapperImplementation implements SystemWrapper {
//The "standard" output stream
public final PrintStream out = System.out;
//Gets the value of the specified environment variable
public string getenv(string name) {
return System.getenv(name);
}
//Sets the system property indicated by the specified key.
public string setProperty(String key, String value) {
return System.setProperty(key, value);
}
}
Your dependent class will then need to be refactored to include the abstraction
public class TestService {
private SystemWrapper system;
public TestService(SystemWrapper system) throws Exception {
this.system = system;
string key = "app.key";
string name = "my_key_name";
loadTestMethod(key, name);
}
private void loadTestMethod(string key, string name) {
string environmentVariable = system.getenv(name);
system.out.println("Environment variable : " + environmentVariable);
system.setProperty(key, environmentVariable);
}
}
Now for testing you can mock the necessary dependencies as needed without any adverse effects. The implementation will then be used in production when invoking actual code.
Finally I would suggest not having your constructors throwing exceptions. Constructors should mainly be used for assignments of variables.

Related

How to set a #Value in a MicronautTest?

I am using Micronaut as framework for developing an AWS Java Lambda.
Micronaut supports #Value for reading, well, "values".
#io.micronaut.context.annotation.Factory
public class SomeFactory {
public SomeFactory(
#io.micronaut.context.annotation.Value("${NameOfValue}")
final String value) {
...
}
...
}
When testing, I want to set "NameOfValue" to a specific value, how can I do that?
#io.micronaut.test.annotation.MicronautTest
class SomeLambdaIT {
#org.junit.jupiter.api.Test
void aTest() {
// When this test runs, "NameOfValue" shall be set to a specific value
}
}
When testing, I want to set "NameOfValue" to a specific value, how can
I do that?
You have a number of options.
One option is to define src/test/resources/application-test.yml and define the config setting there. That file will only be loaded in the test environment and any settings defined in that file will supersede values defined in src/main/resources/application.yml.
Another option that might make sense if you only want the special setting in play for this particular test is you can do something like this...
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
#MicronautTest(propertySources = "classpath:some-special-test-props.properties")
public class SomeTest {
#Test
void someTest() {
// ...
}
}
Then define src/test/resources/some-special-test-props.properties and assign the value there.
Yet another option is to mark your test with #Property:
import io.micronaut.context.annotation.Property;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
#MicronautTest
#Property(name="some.config.value", value = "My Test Value")
public class SomeTest {
#Test
void someTest() {
// ...
}
}
I hope that helps.
EDIT
A comment below includes "I did give it a try, but the #Property solution nor the some-special-test-props.properties works in my case.". I have created a sample app demonstrating each of these techniques. See the project at https://github.com/jeffbrown/markusschultevalue.
https://github.com/jeffbrown/markusschultevalue/blob/8131e96492356180e2c7fade09603bd41f8c8829/src/main/java/markusschultevalue/SomeWidget.java
package markusschultevalue;
public class SomeWidget {
private final String name;
public SomeWidget(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
https://github.com/jeffbrown/markusschultevalue/blob/master/src/main/java/markusschultevalue/SomeFactory.java
package markusschultevalue;
import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Value;
#Factory
public class SomeFactory {
private final String name;
// there are better ways to do this but
// this is consistent with the code in the
// question being asked...
public SomeFactory(#Value("${some.config.value}") String name) {
this.name = name;
}
#Bean
public SomeWidget createWidget() {
return new SomeWidget(name);
}
}
https://github.com/jeffbrown/markusschultevalue/blob/8131e96492356180e2c7fade09603bd41f8c8829/src/test/java/markusschultevalue/PropertyAnnotationTest.java
package markusschultevalue;
import io.micronaut.context.annotation.Property;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import static org.junit.jupiter.api.Assertions.assertEquals;
#MicronautTest
#Property(name="some.config.value", value="Some Widget Name")
public class PropertyAnnotationTest {
#Inject
SomeWidget someWidget;
#Test
void testWidget() {
assertEquals("Some Widget Name", someWidget.getName());
}
}
https://github.com/jeffbrown/markusschultevalue/blob/8131e96492356180e2c7fade09603bd41f8c8829/src/test/java/markusschultevalue/ConfigFileTest.java
package markusschultevalue;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import static org.junit.jupiter.api.Assertions.assertEquals;
// This will load the config value
// from src/test/resources/some-widget-test-config.yml
#MicronautTest(propertySources = "classpath:some-widget-test-config.yml")
public class ConfigFileTest {
#Inject
SomeWidget someWidget;
#Test
void testWidget() {
assertEquals("Some Other Widget Name", someWidget.getName());
}
}
https://github.com/jeffbrown/markusschultevalue/blob/8131e96492356180e2c7fade09603bd41f8c8829/src/test/resources/some-widget-test-config.yml
some:
config:
value: Some Other Widget Name
Note that in your example you are referencing a config variable with "${NameOfValue}". If that is actually the name of your config variable, note that in code you need to reference that in valid kebab-case which would be "${name-of-value}".
I hope that helps.

how to do junit test for data base insertion using hibernate

I was trying to do j-unit test for project which insert values into database using hibernate classes. The program is creating tables and inserting values into database. but i am not able to do the j-unit part for the test?
I have attached the java table, but the value that i inserting using the test file is not display when i debugged it?
Sample.java
#Entity
public class Sample {
#Id
private int sid;
private String name;
public void set_sid(int sid)
{
this.sid=sid;
}
public void set_name(String name)
{
this.name=name;
}
public int get_sid()
{
return sid;
}
public String get_name()
{
return name;
}
}
SampleInsert.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class SampleInsert {
private Sample s;
private static SessionFactory sf;
public void insert() {
sf = new Configuration().configure(new File("C:/Users/ns068002/eclipse-workspace/JAXRS-HelloWorld1/src/main/java/com/javacodegeeks/enterprise/rest/jersey/hibernate.cfg.xml")).buildSessionFactory();
Session session = sf.getCurrentSession();
session.beginTransaction();
Sample s=(Sample) session.get(Sample.class, 1);
System.out.println(s+"2");
System.out.println(s.get_name());
session.getTransaction().commit();
}
}
SampleInsertTest.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class SampleTest {
Session session;
SampleInsert st;
#Before
public void setUp() {
session=mock(Session.class);
st=new SampleInsert();
}
#Test
public void test() {
Sample s=new Sample();
s.set_sid(1);
s.set_name("gopal");
Mockito.when(session.get(Sample.class,1)).thenReturn(s);
System.out.println(s+"1");
st.insert();
}
}
Looking at your code, I can not see how you would be able to mock/stub the Session or SessionFactory as neither of these things are "injected" into the class SampleInsert.
By "injected" I mean that the values are not passed into the class in some way, this is usually done using annotation with a framework like Spring, or via constructors.
It should be remembered that we are not testing the thing we are mocking, we are replacing the thing being mocked with a representation that is much simpler in order to test a component that makes use of the thing being mocked.
As an example of how you might use Mockito:
public interface SomethingToMock {
int returnSomeValueFor(int value);
}
public class ToBeTested {
private SomethingToMock session;
public ToBeTested(SomethingToMock session) {
this.session = session;
}
public void methodToTestA(int value) {
returnSomeValueFor(value);
}
public int methodToTestB(int value) {
int i = returnSomeValueFor(value);
return i * i;
}
}
#RunWith(MockitoJUnitRunner.class)
public class SomeTests {
#Mock
private SomethingToMock aMock;
private ToBeTested underTest;
#Before
public void setUp() {
underTest = new ToBeTested(aMock);
}
#Test
public void testOne() {
underTest.MethodToTestA(3);
verify(aMock).returnSomeValueFor(3);
}
#Test
public void testTwo() {
when(aMock.returnSomeValueFor(3)).thenReturn(2);
int r = underTest.methodToTestB(3);
assertEqual(r, 4);
}
}
In the example above we create an interface, this represents the thing to be mocked, we should aim to only mock interfaces and only those we or our team has created.
We then have a class that we need to test that uses the interface ToBeTested we can assume that concrete implementation of the interface are tested elsewhere in the project.
ToBeTested has two methods to test, one that has no return so has no side effects that we can see. The second method does some processing and has a side effect.
We then create a test class to test both methods, we insure it is setup to use Mockito (#RunWith(MockitoJUnitRunner.class) we then setup a mock using #Mock, the final setup step is to ensure our class has the mock "injected" into it, this is done in the setUp() method.
Finally we create two tests the first verifies that the mocked method is called, we don't have to set up a when for this in this case as no value will be returned from the method we are testing, just from the method being mocked I believe Mockito will return the default for an int.
The second test tests that a value is returned, thus we setup a when, when the mocked method is called in the way specified in the when the given value is returned and we can assert that the correct value is returned from the method under test, in this case using assertThat
This is the general layout of testing with Mockito. Effective testing is a huge topic, I would suggest you do some research on the web. The Mockito and JUnit docs are very good, and of course GitHub has many projects using both; one idea might be to look at the Mockito and Unit on Github and look at their testing.
Also the Mockito documentation does a very good job of explaining how, why and when to use mocking: http://static.javadoc.io/org.mockito/mockito-core/2.25.1/org/mockito/Mockito.html
I hope this helps.

Proxy for abstract class without changing the usage

I have an abstract class (database mapping) implementing an interface where default implementations are injected at runtime (this is part of another library and cannot be changed).
I want to override one of the default implementation via a proxy (as that seems like the way to override this).
public abstract class Table1 implements Storable<Table1>
{
#Sequence("ID_SEQUENCE")
#Alias("ID")
public abstract String getID();
public abstract void setID(String ID);
#Alias("NAME")
public abstract String getAvailabilityZone();
public abstract void setAvailabilityZone(String value);
}
public interface Storable<S extends Storable<S>> {
//a bunch of method definition.
boolean tryLoad() throws Exception;
}
Let's say I want to override tryLoad() method to do my own things instead of what the generated code provides. Given the nature of the library, it is not something I can achieve by simple #Override.
The simple way this is currently used is as following:
public void method() {
Table1 t = Repository.storageFor(Table1.class).prepare();
t.setName( "temp" );
if (!t.tryLoad())
t.tryInsert();
}
I want to proxy tryLoad() without making changes in all the methods across the whole codebase - that would be to get proxied instance instead of actual one and perform the operation on that.
Is there any recommended way to achieve this?
Thanks!
I woke up last night and felt bored, so despite your lack of feedback I created a little Carbonado showcase project and shared it on GitHub. I made three commits:
Initial commit with Maven project already prepared for AspectJ and a JUnit test for me to find out how Carbonado actually works, because I had never used it before.
Add failing unit test for behaviour of tryLoad() expected to be provided by aspect.
Add aspect to make unit test pass. Aspect hooks into tryLoad() and auto-creates non-existent record. I do not know if I guessed right what you actually wanted to achieve, but if it was a different thing, just change the aspect implementation.
Sample code
Carbonado storable:
package de.scrum_master.app;
import com.amazon.carbonado.Nullable;
import com.amazon.carbonado.PrimaryKey;
import com.amazon.carbonado.Storable;
#PrimaryKey("ID")
public interface StoredMessage extends Storable<StoredMessage> {
long getID();
void setID(long id);
#Nullable String getMessage();
void setMessage(String message);
}
Aspect:
package de.scrum_master.aspect;
import com.amazon.carbonado.Storable;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class CarbonadoAspect {
#Around("call(boolean tryLoad()) && target(storable)")
public boolean tryInsertIfNotFound(ProceedingJoinPoint thisJoinPoint, Storable storable) throws Throwable {
System.out.println(thisJoinPoint);
if ((boolean) thisJoinPoint.proceed())
return true;
System.out.println("Not found: " + storable + " -> inserting");
return storable.tryInsert();
}
}
JUnit test:
package de.scrum_master.app;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.amazon.carbonado.FetchException;
import com.amazon.carbonado.PersistException;
import com.amazon.carbonado.Repository;
import com.amazon.carbonado.RepositoryException;
import com.amazon.carbonado.Storage;
import com.amazon.carbonado.SupportException;
import com.amazon.carbonado.repo.map.MapRepositoryBuilder;
import de.scrum_master.app.StoredMessage;
public class CarbonadoTest {
private Repository repo;
private Storage<StoredMessage> storage;
StoredMessage message;
#Before
public void setUp() throws Exception {
repo = MapRepositoryBuilder.newRepository();
storage = repo.storageFor(StoredMessage.class);
message = storage.prepare();
}
#After
public void tearDown() throws Exception {
repo.close();
repo = null;
storage = null;
message = null;
}
// (...)
#Test
public void aspectCreatesNonExistentRecord() throws SupportException, RepositoryException {
message.setID(1);
// Without the aspect this would be false
assertTrue(message.tryLoad());
assertEquals(message.getID(), 1);
assertEquals(message.getMessage(), null);
}
}
Enjoy!

How can Mockito capture arguments passed to an injected mock object's methods?

I am trying to test a service class, which internally makes use of a Spring AMQP connection object. This connection object is injected by Spring. However, I don't want my unit test to actually communicate with the AMQP broker, so I am using Mockito inject a mock of the connection object.
/**
* The real service class being tested. Has an injected dependency.
*/
public class UserService {
#Autowired
private AmqpTemplate amqpTemplate;
public final String doSomething(final String inputString) {
final String requestId = UUID.randomUUID().toString();
final Message message = ...;
amqpTemplate.send(requestId, message);
return requestId;
}
}
/**
* Unit test
*/
public class UserServiceTest {
/** This is the class whose real code I want to test */
#InjectMocks
private UserService userService;
/** This is a dependency of the real class, that I wish to override with a mock */
#Mock
private AmqpTemplate amqpTemplateMock;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testDoSomething() {
doNothing().when(amqpTemplateMock).send(anyString(), any(Message.class));
// Call the real service class method, which internally will make
// use of the mock (I've verified that this works right).
userService.doSomething(...);
// Okay, now I need to verify that UUID string returned by
// "userService.doSomething(...) matches the argument that method
// internally passed to "amqpTemplateMock.send(...)". Up here
// at the unit test level, how can I capture the arguments passed
// to that inject mock for comparison?
//
// Since the value being compared is a UUID string created
// internally within "userService", I cannot just verify against
// a fixed expected value. The UUID will by definition always be
// unique.
}
}
The comments in this code sample hopefully lay out the question clearly. When Mockito injects a mock dependency into a real class, and unit tests on the real class cause it to make calls to the mock, how can you later retrieve the exact arguments that were passed to the injected mock?
Use one, or more, ArgumentCaptors.
It is unclear what your types are here, but anyway. Let's suppose you have a mock which has a method doSomething() taking a Foo as an argument, then you do this:
final ArgumentCaptor<Foo> captor = ArgumentCaptor.forClass(Foo.class);
verify(mock).doSomething(captor.capture());
final Foo argument = captor.getValue();
// Test the argument
Also, it looks like your method returns void and you don't want it to do anything. Just write this:
doNothing().when(theMock).doSomething(any());
You can hook doAnswer() to the stub of the send() method on amqpTemplateMock and then capture the invocation arguments of AmqpTemplate.send().
Make the first line of your testDoSomething() be this
Mockito.doAnswer(new Answer<Void>() {
#Override
public Void answer(final InvocationOnMock invocation) {
final Object[] args = invocation.getArguments();
System.out.println("UUID=" + args[0]); // do your assertions here
return null;
}
}).when(amqpTemplateMock).send(Matchers.anyString(), Matchers.anyObject());
putting it all together, the test becomes
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public class UserServiceTest {
/** This is the class whose real code I want to test */
#InjectMocks
private UserService userService;
/** This is a dependency of the real class, that I wish to override with a mock */
#Mock
private AmqpTemplate amqpTemplateMock;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testDoSomething() throws Exception {
Mockito.doAnswer(new Answer<Void>() {
#Override
public Void answer(final InvocationOnMock invocation) {
final Object[] args = invocation.getArguments();
System.out.println("UUID=" + args[0]); // do your assertions here
return null;
}
}).when(amqpTemplateMock).send(Matchers.anyString(), Matchers.anyObject());
userService.doSomething(Long.toString(System.currentTimeMillis()));
}
}
This gives output
UUID=8e276a73-12fa-4a7e-a7cc-488d1ce0291f
I found this by reading this post,
How to make mock to void methods with mockito

Powermock : Mocked method still called

First of all, please know that I've searched SO before asking this question, but I was unable to find a satisfying answer.
I'm using JUnit4 and Powermock 1.5.5 (with mockito 1.9.5)
My problem is the following : in my unit tests, I need to mock a static method in a class I can't modify. I only want to mock one method, and not the whole class, so I went for a spy.
Here's what I have so far :
[...]
import static org.mockito.Matchers.*;
import static org.powermock.api.mockito.PowerMockito.*;
#RunWith(JUnitParamsRunner.class)
#ContextConfiguration(locations={"classpath:applicationContext-test.xml"},
loader=MockWebApplicationContextLoader.class)
#MockWebApplication(name="my-app")
#PrepareForTest(value = {
Role.class
})
public class MyTest {
#Rule
public PowerMockRule powerMockRule = new PowerMockRule();
#Before
public void setUp() throws Exception {
initSpring();
mockRoleServices();
}
private void mockRoleServices() throws Exception {
spy(Role.class);
RoleAnswer roleAnswer = new RoleAnswer(RoleEnum.ADMIN);
when(Role.hasAdministratorRole(anyLong(), anyLong(), anyLong()))
.then(roleAnswer);
}
private class RoleAnswer implements Answer<Boolean> {
private RoleEnum roleEnum;
private RoleAnswer(RoleEnum roleEnum) {
this.roleEnum = roleEnum;
}
#Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
return getRenderRequest().getUserRole() != null &&
getRenderRequest().getUserRole().equals(roleEnum);
}
}
}
Here's the problem : the method Role.hasAdministratorRole() is called instead of being mocked
Here's what I tried so far :
Using mockStatic(Role.class) instead of the spy() method. As expected, all methods are mocked, so I end up getting an NPE before Role.hasAdministratorRole() is called
Doing something like doAnswer(...).when(...). I get a runtime error with powermock telling me my mock is not complete (which actually confirms that something's wrong either with my code or with the lib itself)
Trying to declare the method by its name rather than calling it directly : when(Role.class, "hasAdministratorRole", long.class, long.class, long.class). Same behavior
A bunch of other things I don't recall anymore.
Your help will be greatly appreciated.
Thanks !
EDIT : Thanks to SrikanthLingala's answer, I was able to pinpoint the problem.
This didn't work :
when(Role.hasAdministratorRole(anyLong(), anyLong(), anyLong()))
.thenAnswer(roleAnswer);
but this did :
doAnswer(roleAnswer).when(Role.class, "hasSiteAdministratorRole",
anyLong(), anyLong(), anyLong());
So switching then when() and the answer() worked
As I do not have all of your implementations, I setup some dummy implementations and made a similar setup like yours. The below code works fine for me.
import static junit.framework.Assert.assertTrue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(value = {
Role.class
})
public class RoleTest {
#Test
public void mockRoleServices() throws Exception {
PowerMockito.spy(Role.class);
PowerMockito.doAnswer(new RoleAnswer(RoleEnum.ADMIN)).when(Role.class, "hasAdministratorRole", Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
Role.printOut();
assertTrue(Role.hasAdministratorRole(1, 1, 1));
}
private class RoleAnswer implements Answer<Boolean> {
private RoleEnum roleEnum;
private RoleAnswer(RoleEnum roleEnum) {
this.roleEnum = roleEnum;
}
public Boolean answer(InvocationOnMock invocation) throws Throwable {
return true;
}
}
}
Dummy Role class:
public class Role {
public static Boolean hasAdministratorRole(long a, long b, long c) {
System.out.println("Inside hasAdministratorRole");
return a + b + c < 0;
}
public static void printOut() {
System.out.println("Inside Printout");
}
}
My test case does not printout Inside hasAdministratorRole, but prints out Inside Printout
Hope this helps
Glad you have solved your issue, this just a warning for everyone else having a similar issue.
Project setup:
Powermock 1.5.5
Mockito 1.9.5
TestNG 6.8.8
Powermock is not taking into account mocks/spies created in a method annotated with #BeforeTest
E.g.:
#BeforeTest
public void setup(){
testee = mock(AClass.class);
}
It gets discarded and then it is entering the mocked method instead of returning the expected result OR throwing all kinds of strange exceptions. When moved to a common test method, it suddenly starts working:
#Test
public void test(){
AClass testee = mock(AClass.class);
....
}
Possibly it is a bug.

Categories