Spring-boot Redis JMS JUnit - junit

I am using Redis Server for message broker in my spring boot application.
Is there any simple way to Junit my publish and receive API?
e.g :
Publisher :
public String publish(Object domainObj) {
template.convertAndSend(topic.getTopic(), domainObj.toString());
return "Event Published";
}
Receiver :
public class Receiver implements MessageListener {
#Override
public void onMessage(Message message, byte[] bytes) {
System.out.println("Consumed Message {}" + message);
}
}
I am using JedisConnectionFactory and RedisMessageListenerContainer and RedisTemplate for my implementation
#Configuration
#EnableRedisRepositories
public class RedisConfig {
#Bean
public JedisConnectionFactory connectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
configuration.setHostName("localhost");
configuration.setPort(6379);
return new JedisConnectionFactory(configuration);
}
#Bean
public RedisTemplate<String, Object> template() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new JdkSerializationRedisSerializer());
template.setValueSerializer(new JdkSerializationRedisSerializer());
template.setEnableTransactionSupport(true);
template.afterPropertiesSet();
return template;
}
#Bean
public ChannelTopic topic() {
return new ChannelTopic("common-channel");
}
#Bean
public MessageListenerAdapter messageListenerAdapter() {
return new MessageListenerAdapter(new Receiver());
}
#Bean
public RedisMessageListenerContainer redisMessageListenerContainer() {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory());
container.addMessageListener(messageListenerAdapter(), topic());
return container;
}

Unit Testing Receiver and Publisher implementation is quite straight.
JUnit 5 coupled with Mockito extension should do the job.
For example for testing that :
public String publish(Object domainObj) {
template.convertAndSend(topic.getTopic(), domainObj.toString());
return "Event Published";
}
I expect that topic and template be fields of the current class.
These fields could be set by constructor.
So you could write something that check that convertAndSend() is eventually executed with the correct parameters :
#Mock
RedisTemplate<String, Object> templateMock;
#Test
void publish(){
Topic topicFixture = new Topic(...);
Object domainObjFixture = new FooBar(...);
Publisher publisher = new Publisher(templateMock, topicFixture);
//when
publisher.publish(domainObjFixture);
// then
Mockito.verify(templateMock)
.convertAndSend(topicFixture.getTopic(), domainObjFixture);
}
But I don't think that the unit test of these two classes be enough because it never tests the final things : the JMS processing performed by Redis backend.
Particularly, the RedisConfig part that you set with specific things as serializers that have important side effects on the processing.
For my part, I try to always write integration or partial integration tests for Redis backend stuffs to ensure a good no regression harness.
The java embedded-redis library is good for that. It allows to start a redis server
on localhost (works on Windows as well as on Linux).
Starting and stopping the redis server is as simple as :
RedisServer redisServer = new RedisServer(6379);
redisServer.start();
// do some work
redisServer.stop();
Move the start() in the #BeforeEach and the stop() in the #AfterEach and the server is ready.
Then it still requires some adjustments to ensure that the redis configuration specified in Spring is well setup during the tests while using your local redis server and not the "real" redis server. Not always simple to set but great when it is done !

The simplest way to unit test this is to use embedded-redis module. What you do is in BeforeAll you can start embedded Redis and stop the embedded Redis in AfterAll method.
You can also PostConstruct PreDestroy annotations to accomplish this.
If you're looking for Junit5 then you can find the code in my repo here
See BootstrapRedis annotation and their usage here
https://github.com/sonus21/rqueue/blob/7ef545c15985ef91ba719f070f7cc80745525047/rqueue-core/src/test/java/com/github/sonus21/rqueue/core/RedisScriptFactoryTest.java#L40

Related

Unable to Mock functions inside static method Powermock

I am writing unit test for the below code using junit and mockito
public class Abc implements Runnable
{
private static ServerSocket server;
private static int port;
public Abc(int cPort)
{
port = cPort;
}
public void run()
{
init();
}
public static void init()
{
try {
server = new ServerSocket(port);
...something...
client.close();
}
}
catch(IOException e)
{
System.out.println("Exception inside init()...");
e.printStackTrace();
}
}
};
Unit test I have written
#RunWith(PowerMockRunner.class)
#PrepareForTest({ServerSocket.class})
public class abcTest {
#Mock (name = "server") //same name as private var.
ServerSocket mockServer;
#InjectMocks
Abc abc;
#Test
public void testInit() throws Exception {
int port = 1880;
Socket mockClient = Mockito.mock(Socket.class);
PowerMockito.whenNew(ServerSocket.class).
withArguments(anyInt()).thenReturn(mockServer);
abc = new Abc(port);
Abc.init();
PowerMockito.verifyNew(ServerSocket.class).withArguments(port);
}
};
But the call always go to original function definition. I am using junit 4.11 with mockito 2.28.2 and powermockito 2.0.2. I'm using java after a long time. Now its feel like kind of new. Please correct me if anything wrong in the code also.
You will need to change your PrepareForTest annotation
to #PrepareForTest({Abc.class}).
From the PowerMockito docu:
This annotation tells PowerMock to prepare certain classes for testing. Classes needed to be defined using this annotation are typically those that needs to be byte-code manipulated
In this case that refers to the class which creates the new instance of ServerSocket. ServerSocket itself is a non-final public class that does not require special handling from PowerMockito (instead Mockito can deal with this class on its own).
You could also change your test to do the following:
#Test
public void testInit() throws Exception {
int port = 1880;
ServerSocket mockServer = Mockito.mock(ServerSocket.class);
PowerMockito.whenNew(ServerSocket.class)
.withArguments(Mockito.anyInt()).thenReturn(mockServer);
Abc.port = port;
Abc.init();
PowerMockito.verifyNew(ServerSocket.class).withArguments(port);
}
(This first point is unrelated to whether the test fails or succeeds)
I do not know why you mix object's and static method behaviour together, but I think you should change that.In the test instead of creatic an ABC object, just could just set the static port variable directly.
Or alternatively change the whole ABC class into an object.
#InjectMocks failed for me as there is no default constructor
(Actually I got an error message in the console when trying to execute your code)
Additonaly you create a new instance of ABC in your test, which would have overwritten the things done by the annotations. Also as server is created during the init call, there is no need to inject a mock for it.
powermockito 2.0.2 actually depends on junit 4.12, so I am not sure what effects downgrading to an older version might have.
Socket mockClient seemed somewhat unrelated to the code your posted, so I removed it from my example in the answer, however as you use a client (I assume that is your Socket) in your code your probably need to do some mocking for that as well and provide the mock to the method accordingly.

How to execute some code after Cucumber report is built?

I use Cucumber for jUnit runner to run BDD tests like this:
#RunWith(Cucumber.class)
#CucumberOptions(
format = {"pretty", "json:target/cucumber.json"},
glue = {"com.company.bdd.steps"},
features = {"classpath:bdd-scenarios"},
tags = {"~#skip"}
)
public class CucumberTests {
}
I would like to have beautiful HTML reports from https://github.com/damianszczepanik/cucumber-reporting
And i made jUnit #AfterClass method:
#AfterClass
public static void buildReport() throws Exception {
List<String> srcReportJson = Collections.singletonList("target/cucumber.json");
Configuration configuration = new Configuration(new File("target"), "AEOS BDD Integration Tests");
new ReportBuilder(srcReportJson, configuration).generateReports();
}
The problem is that cucumber.json is empty when #AfterClass method executes. Hence i can't build pretty HTML report.
Is there any hook which i can use to execute some code after cucumber json report is already built?
PS: Cucumber v.1.1.8 is used and Java 1.7 so i was not able to try ExtendedCucumberRunner
Have you considered adding shutdown hook? Here is an example on how to add one. Code in run() method supposed to be executed before JVM shuts down.
You can take a look at custom formatter of cucumber:
Thank you for your suggestions but I just decided to use already existing Maven plugin and execute it's goal right after test goal.
wjpowell posted this suggestion in the cucumber-jvm issues:
"You don't need to do this in cucumber. Use the #beforeclass and #afterclass annotation from within the JUnit test used to run the cucumber tests. This has the benefit of running only for the features specified by the paths or tags options.
#RunWith(Cucumber.class)
#Cucumber.Options(format = {"html:target/cucumber-html-report", "json-pretty:target/cucumber-json-report.json"})
public class RunCukesTest {
#BeforeClass
public static void setup() {
System.out.println("Ran the before");
}
#AfterClass
public static void teardown() {
System.out.println("Ran the after");
}
}
"

Multiple instance of DynamoDbLocal for each unit test class or singleton instantiation

I am trying to use DynamoDbLocal server for unit test cases.
And came up with two options,
Either define a junit class rule which starts local server before class and stops it after class. So essentially it will start and stop server for each unit test class.
public class MyDynamoDbLocalServerRule extends ExternalResource {
#Override
protected void before() throws Throwable {
myInMemoryDynamoDbServer.start();
}
#Override
protected void after() throws Throwable{
inMemoryDynamoDbServer.stop();
}
OR
Singleton instance :
public static DynamoDBProxyServerContainer createInstance(final int portToListenIn) {
if (dynamoLocal == null) {
synchronized (DynamoDBProxyServerContainer.class) {
if (dynamoLocal == null) {
dynamoLocal = new DynamoDBProxyServerContainer(portToListenIn);
}
}
}
return dynamoLocal;
}
private DynamoDBProxyServerContainer(final int portToListenIn) {
this.startServer(portToListenIn);
getRuntime().addShutdownHook(new Thread(() -> stopServer()));
}
Which one would you recommend and do you have better of doing this ? Please note i should be able to use it with Guice dependency injection framework.
I would recommend Singleton approach as creating the database instance for each test case will be a time consuming option. Also, if you have many test cases, the unit testing is likely to take more time to complete. If you have continuous integration, the build and unit test would take more time.
As the unit tests run in sequential manner, you don't need separate instance for each test case.

Does Jodd framework provide mechanism to inject petitebeans references for objects created by other frameworks

Does Jodd framework provide mechanism to inject petitebeans references for the objects created by other frameworks.
Below are scenarios
- Domain/Service objects are created by Spring Framework
- Domain objects created are by ORM Frameworks
- These objects need to be injected with Repository/DAO object (Singleton objects registered as PetiteBean via AutomagicPetiteConfigurator)
Below is sample code, after petite container is shutdown, initMethod() is invoked when pc.getBean(Greetings.class).message(null) is invoked and destroyMethod() is not invoked, can you please point me what I am doing wrong?
#PetiteBean("greetings")
public class EnglishGreetings implements Greetings {
#Override
public String message(String message) {
if (message == null) {
return "defaultMessage";
}
return message;
}
#PetiteInitMethod
public void initMethod() {
System.out.println("Entered initMethod");
}
#PetiteDestroyMethod
public void destroyMethod() {
System.out.println("Entered destroyMethod");
}
}
public class GreetingRunner {
final static Logger logger = LoggerFactory.getLogger(GreetingRunner.class);
#PetiteInject
public Greetings greetings;
public static void main(String s[]) {
jodd.log.LoggerFactory.setLoggerFactory(new Slf4jLoggerFactory());
PetiteContainer pc = new PetiteContainer();
AutomagicPetiteConfigurator configurator = new AutomagicPetiteConfigurator();
configurator.setIncludedEntries("com.rans.*");
configurator.configure(pc);
pc.shutdown();
System.out.println(pc.getBean(Greetings.class).message(null));
}
}
Destroy method has not been invoked because of lazy aspect of Petite - if bean has not been used, no destroy method will be called. The same applies to init methods. If bean is not used, Petite simple ignores it.
Now back to the question:
Does Jodd framework provide mechanism to inject petitebeans references for the objects created by other frameworks.
Technically, yes - if you overwrite it :) See PetiteProxettaContainer. You may override getBean and use 3rd party container to fetch the bean. Actually, you may override createBeanDefinitionForRegistration method to register the bean in the different container. To be honest, we might make this more obvious :)
(Sorry for late response)

Call a Rest method with mockito

I use Jersey and I have the following Rest function which returns a JSON string when my server is deployed:
#GET
#Path("getallemployees")
#Produces("application/json")
public Response getAllEmployees() {
//building the entity object which is List<Employee>
return Response.ok(entity).build();
}
I need to develop some unit tests (not integration testing) and I want to somehow mock the HTTPRequest that invokes this method and then get the json String. The best option would be to use mockito for this.
Is there any suggestion on how to do it ?
Thanks !!
The problem is that the method returns a Response object to the caller which is deep within the framework code. It doesn't return JSON strings.
You can use Mockito, if you need to mock something inside the method itself. That should work.
But you may need to take the value returned by the method and convert it to JSON like this if you are using Jackson with Jersey.
Response response = getAllEmployees();
Object retval = response.getEntity();
try {
ObjectMapper mapper = new ObjectMapper();
// I like this formatting. You can change it.
mapper.configure(Feature.INDENT_OUTPUT, true);
mapper.configure(Feature.WRITE_ENUMS_USING_TO_STRING, true);
mapper.configure(Feature.USE_ANNOTATIONS, false);
mapper.configure(Feature.FAIL_ON_EMPTY_BEANS, false);
mapper.setSerializationInclusion(Inclusion.NON_NULL);
mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
mapper.getSerializationConfig().withSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
String json = mapper.writeValueAsString(retval);
... assert something about the string
} catch (JsonProcessingException e) {
// do something
} catch (IOException e) {
// do something
}
Some of this is guess work and speculation on my part but it may help. You could try using the Jersey Test Framework with the InMemoryTestContainerFactory:
It starts Jersey application and directly calls internal APIs to handle request created by client provided by test framework. There is no network communication involved. This containers does not support servlet and other container dependent features, but it is a perfect choice for simple unit tests.
It looks like to use it, all you need to do is extend JerseyTest and then override getTestContainerFactory() and follow the rest of the instructions, e.g.:
public class EmployeeResourceTest extends JerseyTest {
#Override
protected Application configure() {
// set up employee resource with mock dependencies etc...
return new ResourceConfig().registerInstances(employeeResource);
}
#Test
public void getAllEmployees() {
final String response = target("getallemployees").request().get(String.class);
// assert etc...
}
}
I used registerInstances instead of registerClasses in configure() as it looks like you can present a ready made Resource but set up with any mock dependencies you may want - although I haven't tried this myself.
The test class is a bit inflexible as you can only do one-time set up of dependencies in the configure() method, so it might be worth investigating using the MockitoJUnitRunner - although I'm not sure if it will work with the JerseyTest inheritance. It could allow you to do add behaviour to mocks in each #Test method, e.g.:
#Mock
private EmployeeResourceDependency dependency;
#InjectMocks
private EmployeeResource employeeResource;
// configure() as above but without mock setup up etc...
#Test
public void getAllEmployees() {
given(dependency.getEmployees()).willReturn(...);
// etc...
But like I said it might not be possible to mix them at all.