How to clear/ignore ehcache's data and test via MockRestServiceServer? - java

We are running our component test-cases in which we load some data using cache.. Now the problem is when we try other test-cases, we want to reset the cache because it then doesn't test with the other data. How can we achieve this. We are using spring boot with Java and using Ehcache.

You can inject the org.springframework.cache.CacheManager bean into your tests and use it to clear the cache before or after each test. Assuming there is a cache named testCache, a test class that clears the cache would look something like below:
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cache.CacheManager;
#SpringBootTest
public class IntegrationTest {
#Autowired
private CacheManager cacheManager;
#BeforeEach
public void setup() {
cacheManager.get("testCache").clear();
}
#Test
public void testSomething() {
}
}
You can find a reference spock-based test that does the same thing on github

Related

Could not autowire. No beans of 'MockMvc' type found - Imported correctly, configured correctly and works fine in other project?

In my Controller test class I am trying to test use Mockito and MockMVC to test the controller layer independently.
I have reused code from my previous project but for some reason it is not working in this new project despite containing identical configuration, imports etc.
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#AutoConfigureMockMvc
#WebMvcTest(controllers = UserController.class)
public class UserControllerTests {
#Autowired
MockMvc mockMvc;
#MockBean
private UserService userService;
#MockBean
private UserRepository userRepository;
#Test
public void FindPlayersSuccessfully() throws Exception {
String json = "{\"userID\":\"1\"}";
mockMvc.perform(post("/api/v1/users/find-users")
.contentType(MediaType.APPLICATION_JSON)
.content(json).characterEncoding("utf-8"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.response").value("Success"));
}
The 'MockMvc mockMvc' autowire is highlighted in red by IDEA and when I hover over the error it says 'Could not autowire. No beans of 'MockMvc' type found'
Also, something possibly strange I noticed is that when I added imports one by one, the MockMvc import did work and the highlight disappeared, but when I added the:
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import, the problem occured.
Thanks for any help!
I had the same problem. Try in Intelij Idea File-> Settings->Editor->CodeStyle->Inspections, then choose Spring Core -> Code and change "Incorrect injection point autowiring in Spring bean components" severity from Error to Warning.

Using GCP Secret Manager in integration tests in Java

I have a pretty big code base written in Java. I have a lot of integration tests with both Kafka and Bigtable using JUnits ExternalResource. I have introduced fetching of secrets from GCP Secret Manager in my code. I now want to write integration tests for that as well.
So my scenario is that I want to create a mock username/password, create a secret of that username/password in my mock GCP Secret Manager, access the secrets and then use it to connect to my mock-service that requires that username/password. So, in reality, I'm connecting to a Kafka broker in my test with SSL and I want to simulate the entire flow with fetching of secrets.
The problem is, I can't find any documentation on how to do it. Google has great other documentation on how to emulate Bigtable, but I can't find any documentation on how to emulate/mock a Secret Manager. Has anyone ran into something similar?
In case you are using Spring Boot you may mock SecretManagerOperations interface using #TestConfiguration as follows:
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.test.web.servlet.MockMvc;
import com.google.cloud.spring.secretmanager.SecretManagerOperations;
#AutoConfigureMockMvc
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MySecretIntegrationTest {
#Autowired
private MockMvc mockMvc;
#Test
public void testGettingSecretResource() throws Exception {
mockMvc.perform(get("/api/resource")).andExpect(status().isOk());
}
#TestConfiguration
public static class SecretManagerConfiguration {
#Bean
#Primary
public SecretManagerOperations secretManagerProducer() throws Exception{
SecretManagerOperations secretManager = mock(SecretManagerOperations.class);
when(secretManager.getSecretString("secret_id")).thenReturn("top secret");
return secretManager;
}
}
}
Annotate the producer method with #Primary so that the mocked bean gets autowired during the test instead of the default implementation SecretManagerTemplate.
"GCP doesn't have any Emulator for Secret Manager" - #Guillaume Blaquiere.

How to Mock a Kafka Consumer endpoint on a Camel Route?

I have a Camel endpoint which is basically a Kafka Consumer reading from a topic and sending the information to a database. It is working fine, however, I am struggling to unit test it as I haven't been able to mock the Kafka endpoint. Can anyone help me in mocking a Kafka Consumer in a Camel Route?
#Override
public void configure() {
from(kafka:eph?brokers=localhost:9092...).routeId("KafkaConsumer")
.to(direct:updateDatabase)
}
To unit test your route, you may do that with a standard camel spring boot test.
During the test, the Kafka producer(in Camel's view) can be swapped in with a direct component and mock messages can be delivered there. To see if your routes are processing those messages properly, Mock endpoints can be used.
//Route definition
#Component
public class KafkaRoute extends RouteBuilder {
public static final String KAFKA_ROUTE_NAME = "kafka-route";
#Override
public void configure() throws Exception {
from("kafka:eph?brokers=localhost:9092").routeId(KAFKA_ROUTE_NAME)
.log(LoggingLevel.INFO, "Message: ${body} received on the topic: ${headers[kafka.TOPIC]} ")
.to("direct:updateDatabase");
from("direct:updateDatabase").log(LoggingLevel.INFO, "DB Updated.");
}
}
import java.util.HashMap;
import java.util.Map;
import org.apache.camel.CamelContext;
import org.apache.camel.EndpointInject;
import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.AdviceWithRouteBuilder;
import org.apache.camel.component.kafka.KafkaConstants;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.spring.CamelSpringBootRunner;
import org.apache.camel.test.spring.MockEndpoints;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
#RunWith(CamelSpringBootRunner.class)
#SpringBootTest
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
#MockEndpoints("direct:*")
public class KafkaRouteTest {
#Autowired
CamelContext camelContext;
#Produce
ProducerTemplate mockKafkaProducer;
#EndpointInject("mock:direct:updateDatabase")
MockEndpoint finalSink;
#Test
public void testKafkaRoute() throws Exception {
//Here we swap the FROM component in the KafkaRoute.KAFKA_ROUTE_NAME with a direct component, direct:kafka-from
AdviceWithRouteBuilder.adviceWith(camelContext, KafkaRoute.KAFKA_ROUTE_NAME, routeBuilder -> {
routeBuilder.replaceFromWith("direct:kafka-from");
});
Map<String, Object> headers = new HashMap<>();
headers.put(KafkaConstants.TOPIC, "testTopic");
//Send mock message to the route
mockKafkaProducer.sendBodyAndHeaders("direct:kafka-from", "test-body", headers);
//Assertions. You may do additional assertions with the likes of Mockito
finalSink.expectedBodiesReceived("test-body");
finalSink.expectedHeaderReceived(KafkaConstants.TOPIC, "testTopic");
finalSink.assertIsSatisfied();
}
}
Camel Kafka component is already unit tested, there is no point in replicating all those tests in your code base. However, if you really want to do testing against a real Kafka instance, you may use test containers. Here is a full blown example, from the Camel repository itself, using test containers.
Simply externalize the endpoint URI in a property (for example with Spring Property facility)
from(consumerEndpoint).routeId("KafkaConsumer")
Then in your production configuration, you use the real endpoint
consumerEndpoint=kafka:eph?brokers=localhost:9092...
Whereas in your test configuration, you use a direct endpoint
consumerEndpoint=direct:consumer
This one is easy to trigger from a Camel route test
producer.sendBody("direct:consumer", myMessageBody);

Mocking expected result from service using spring testing framework

I want to write a test case for Restful web service using Spring testing framework. I mocked the service and able to run the testcase successfully.
But, as service is mocked, it is returning the empty response. So, I want to set the expected output from the service.
I can achieve it using different mocking frameworks like Mockito or Jmockit (In below code it is with Mockito).
But, is it possible without any addition/external testing frameworks apart from internal Spring testing framework.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import java.util.Arrays;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {TestContext.class, WebAppContext.class})
#WebAppConfiguration
public class TodoControllerTest {
private MockMvc mockMvc;
#Autowired
private TodoService todoServiceMock;
#Test
public void findAll_ShouldAddTodoEntriesToModelAndRenderTodoListView() throws Exception {
Todo first = new TodoBuilder()
.id(2L)
.description("Lorem ipsum")
.title("Bar")
.build();
/**
Need mocking technique from Spring Testing Framework
*/
when(todoServiceMock.findAll()).thenReturn(Arrays.asList(first));
mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(view().name("todo/list"))
.andExpect(forwardedUrl("/WEB-INF/jsp/todo/list.jsp"))
.andExpect(model().attribute("todos", hasSize(2)))
.andExpect(model().attribute("todos", hasItem(
allOf(
hasProperty("id", is(1L)),
hasProperty("description", is("Lorem ipsum")),
hasProperty("title", is("Foo"))
)
)))
.andExpect(model().attribute("todos", hasItem(
allOf(
hasProperty("id", is(2L)),
hasProperty("description", is("Lorem ipsum")),
hasProperty("title", is("Bar"))
)
)));
}
}
One possible solution is to extend a class that you want to test and override methods that you want to mock up. Then in a separate configuration file you define a bean which would be wired in place of a real object. Next use this configuration in your test class.
This is actually Mockito spy's behaviour. If I were you I would stick to it as it provides more flexibility and saves a lot of boilerplate code.
You aren't showing the relevant part of your configuration, but it should be fully possible. In your TodoService you should have injected your data layer dependencies using their interfaces as per Spring best practices, and those dependencies can be replaced (using Spring config) with dummy/stub classes implementing those interfaces that provide the required test data.

Using Spring's ResourceLoader in tests

I'm #Autowireing a org.springframework.core.io.ResourceLoader into one of my #Service classes.
During the tests, I'd like to get access to an instance of a ResourceLoader, so that it can be injected into the service being tested. What's the best way to get a fully functional instance of ResourceLoader during your tests?
If that's not possible, is there an alternative to ResourceLoader? Essentially, I need to have my service read some static files from the project.
Update:
Started using #RunWith(SpringJUnit4ClassRunner.class) + #ContextConfiguration on my test; however, the ResourceLoader that is now being injected via #Autowire into my service behaves differently than usual (ie. when it's not in the test context). In the test, ResourceLoader#getResource returns a Resource pointing to bad relative path, rather than the proper absolute path which appears during a regular execution.
Some more information discovered while debugging:
During tests, the #Autowired resourceLoader is an instanceof org.springframework.context.support.GenericApplicationContext
During regular execution, resourceLoader is an instance of org.springframework.web.context.support.XmlWebApplicationContext
You can use a DefaultResourceLoader. It handles URL and classpath resources which should be enough for simple tests.
DefaultResourceLoader doesn't need any special setup. Just create a new instance and pass it into your test.
What kind of test do you want to write?
If it's a unit test, you should probably mock ResourceLoader and inject that mock into the service instance. (Use mockito for example)
If it's an integration test, you would be better off using the Spring TestContext framework. Create a spring context that contains all components needed for the test, then annotate your test class with #RunWith(SpringJUnit4ClassRunner.class) +
#ContextConfiguration, which will make it possible to autowire fully configured beans (e.g. the service instance to be tested) in the test class.
I suppose you have your service defined as something like this:
public class ResourceService {
#Autowired
ResourceLoader loader;
}
Now, when you write your test for ResourceService :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({ "classpath:test-config.xml" })
public class ResourceServiceTest {
#Autowired
ResourceService resourceService;
#Test
public void test() {
...
}
}
The Spring TestContext Framework configures instances of your test classes via Dependency Injection. So, when you autowire ResourceService in your test class, Spring will inject the autowired ResourceLoader property into ResourceService.
ENVIRONMENT:
Java: 17
Springboot: 2.6.2
Junit-jupiter:5.8.2
Generally integration tests will need to start up a container to execute the test cases. This can be achieved using the following code:
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.ResourceLoader;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.jupiter.api.Assertions.assertTrue;
#RunWith(SpringRunner.class)
#SpringBootTest
#TestPropertySource(locations = "classpath:application-integration-test.properties")
class TemplateKeyValidatorIT {
#Autowired
ResourceLoader resourceLoader;
#Autowired
private ResourceLoaderService resourceLoaderService;
#Test
void testResourceLoading() {
// Given
String fileName = "myTestFile.txt";
// When
File file = resourceLoaderService.load(fileName);
// Then
assertTrue(file.exists());
}
}
#RunWith(SpringRunner.class): SpringRunner is the base Spring framework Runner. It extends SpringJUnit4ClassRunner, but it’s just an alias to that class.
#SpringBootTest: Annotation is needed to bootstrap the entire container; it creates an ApplicationContext that will be used by the integration tests.
#TestPropertySource(locations = "classpath:application-integration-test.properties"): Loads integration specific application properties.
Note: this will boot strap the real application context but you can separate test configuration class using:
#TestConfiguration
public class MyTestContextConfiguration {
#Bean
public ResourceLoaderService resourceLoaderService() {
return new ResourceLoaderService() {
// implement methods
};
}
}
And this can then be impoerted by your test class using:
#Import(MyTestContextConfiguration.class)

Categories

Resources