How to write integration test of rest api with two threads - spring

what should I use to test a rest api? I want to write integration test with two threads.
I am using Controller->Service->Repository model and want to check if there is any race condition.
I tried with Thread Weaver and something like this but it does not work.
public class MyCounterTests {
private MyCounter counter;
#ThreadedBefore
public void before() {
counter = new MyCounter();
}
#ThreadedMain
public void mainThread() {
counter.increment();
}
#ThreadedSecondary
public void secondThread() {
counter.increment();
}
#ThreadedAfter
public void after() {
assertEquals(2, counter.getCount());
}
#Test
public void testCounter() {
new AnnotatedTestRunner().runTests(this.getClass(), MyCounter.class);
}
}

Related

Mock static variable Mockito

// Service
protected static Processor aProcessor = new AProcessor();
protected static Processor bProcessor = new BProcessor();
protected static Processor chain;
static {
validateProcessor.setNextProcessor(bProcessor);
chain = aProcessor;
}
public void method() {
chain.process(new Abc());
}
// AProcessor
public void process(Abc abc) {
System.out.println("AProcessor");
}
// Test
#Mock
private Processor aProcessor;
#Test
public void test() {
service.method();
verify(aProcessor, times(1)).process(any(Abc.class));
}
I'm trying to mock aProcessor and I want to check that process method called 1 time. But it couldn't mock, it's printing "AProcessor" text. Any suggestion to solve it?

How do I use a different Spring datasource depending on the name of the unit test?

)
I have a rather unusual requirement for a series of unit tests I'm fixing. Basically, a different datasource/transaction manager needs to be used depending on the method name of the unit test.
For example, if the test name ends with UseDB2, then we use the DB2 data source, if it's UseH2 then we use the H2 datasource.
I thought the way to go about this was to use the AbstractRoutingDatasource provided by the Spring framework.
public class TestRoutingDatasSource extends AbstractRoutingDataSource {
#Override
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDatabaseType();
}
}
Using a context holder to select the required datasource:
public class DatabaseContextHolder {
private static final ThreadLocal<DType> contextHolder = new ThreadLocal<DType>();
public static void setDatabaseType(DType databaseType) {
contextHolder.set(databaseType);
}
public static DType getDatabaseType() {
return (DType) contextHolder.get();
}
public static void clearDatabaseType() {
contextHolder.remove();
}
}
I was then going to use the name of the test to set the context; something like this:
public class MyDBUnitTestCase extends
AbstractTransactionalDataSourceSpringContextTests {
protected DataSource dataSource;
protected String schemaName;
public void setDataSource(DataSource aDataSource) {
this.dataSource = aDataSource;
}
public void setSchemaName(String aSchemaName) {
this.schemaName = aSchemaName;
}
protected void onSetUp() throws Exception {
super.onSetUp();
if (getName().endsWith("UsingDB2")) {
DatabaseContextHolder.setDatabaseType(DType.DB2);
}
else {
DatabaseContextHolder.setDatabaseType(DType.H2);
}
}
But of course, this won't work because by the time I've come to check the name of the test, Spring has already configured all the beans (doh!).
Is there some other mechanism I can use to get this to work?
Thanks very much for your time.

Spring boot application that run service in sequential order by passing the sequence at the run time

I want to implement a spring boot application that have 3 services . Now I want to run 3 services from my controller sequentially . I want to pass the the name of service and method as well as input parameters and sequence through controller and want to get the result of each of service . Please let me know how I can achieve these with a simple spring boot application.
Very very high level example. General idea that you need to use "reflection" for create class instance by name and/or call methods dynamically without "if". Pay attention that code can be different if your "service" is spring bean.
interface Service {
void method();
}
class Service1 implements Service {
#Override
public void method() {
// do magic
}
}
class Service2 implements Service {
#Override
public void method() {
// do magic
}
}
class Test {
public void executeMe(String className, String methodName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
// you may need to have full class name with package
Service service = (Service) Class.forName(className).newInstance();
if ("method".equalsIgnoreCase(methodName)) {
service.method();
}
}
}
Update
class Service1 {
public void method1() {
// do magic
}
public void method2() {
// do magic
}
}
class Service2 {
public void method3() {
// do magic
}
}
class Test {
public void executeMe(String className, String methodName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
// you may need to have full class name with package
Service1 service = (Service1) Class.forName(className).newInstance();
if ("method1".equalsIgnoreCase(methodName)) {
service.method1();
}
}
}
with Spring
class Test {
#Autowired
private Service1 service1;
#Autowired
private Service2 service2;
public void executeMe(String className, String methodName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Map<String, Object> map = new HashMap<>();
map.put("service1", service1);
map.put("service2", service2);
// you may need to have full class name with package
if ("service1".equalsIgnoreCase(className)) {
Service1 service1 = (Service1) map.get(className);
if ("method1".equalsIgnoreCase(methodName)) {
service1.method1();
}
}
}
}
Again, this is very very high level meta code.

JMeter Plugin - How to Listen to TestState

I am working on developing a JMeter plugin. I'm trying to create an AbstractVisualizer that is capable of monitoring the current test state. However, implementing the TestStateListener doesn't seem to be working.
I'm testing this by creating a basic listener that has a login to output arbitrary info to JMeter's logging console. When a sample is sent through the Add function, a line is sent to the console. But nothing is ever triggered on the various TestState functions. Is there something more structural I'm missing?
public class TestListener extends AbstractVisualizer
implements TestStateListener
{
private static final Logger log = LoggingManager.getLoggerForClass();
#Override
public void add(SampleResult arg0) {
log.info("add");
}
#Override
public void clearData() {
// TODO Auto-generated method stub
}
#Override
public String getStaticLabel()
{
return "Test Listener";
}
#Override
public String getLabelResource() {
return null;
}
#Override
public void testEnded() {
log.info("Test Ended");
}
#Override
public void testEnded(String arg0) {
log.info("Test Ended");
}
#Override
public void testStarted() {
log.info("Test started");
}
#Override
public void testStarted(String arg0) {
log.info("Test started");
}
}
I'm not sure how to do it in 1 class. I have 2 classes:
The UI:
public class MonitorGui extends AbstractListenerGui
{
// ...
#Override
public TestElement createTestElement()
{
TestElement element = new Monitor();// <-- this is the backend
modifyTestElement(element);
return element;
}
// ...
}
And then the backend goes like this:
public class Monitor extends AbstractListenerElement
implements SampleListener,
Clearable, Serializable,
TestStateListener, Remoteable,
NoThreadClone
{
private static final String TEST_IS_LOCAL = "*local*";
// ...
#Override
public void testStarted()
{
testStarted(TEST_IS_LOCAL);
}
#Override
public void testEnded()
{
testEnded(TEST_IS_LOCAL);
}
#Override
public void testStarted(String host)
{
// ...
}
// ...
}
You may not need to implement SampleListener like I do, but probably other things are quite similar.
I based that implementation on a built-in pair of ResultSaverGui and ResultCollector which are the components that are saving results into the file(s) for Simple Data Writer, Summary Report and so on.

Should the Spring Boot shutdown endpoint shut down the entire JVM process, or just the application context?

I am getting a 200 response from Spring Boot's shutdown endpoint, and I am seeing that the application context shuts down as expected, but then the JVM process itself remains alive forever. Is this the expected behavior of the shutdown endpoint, or is it expected that the process itself would also terminate gracefully?
In http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html, it says that the shutdown endpoint "allows the application to be gracefully shutdown (not enabled by default)".
Thanks Stéphane, I found what was preventing the JVM process from terminating after hitting the /shutdown endpoint. There was a ScheduledExecutor in one of my dependencies that was not being shut down with the application context, and it was preventing the JVM process from shutting down (even after the application context was closed). I wrote a simple example to show how to reproduce the behavior, and another example showing how to resolve it.
This example will NOT terminate the JVM process when you hit /shutdown endpoint:
#SpringBootApplication
public class AppSpringConfiguration {
public static void main(String[] args) {
SpringApplication.run(AppSpringConfiguration.class);
}
#Bean
public ClassWithExecutor ce() {
return new ClassWithExecutor();
}
#PostConstruct
public void startScheduledTask() {
ce().startScheduledTask();
}
#RestController
public static class BusinessLogicController {
#RequestMapping(value = "/hi")
public String businessLogic() {
return "hi";
}
}
public static class ClassWithExecutor {
ScheduledExecutorService es;
ClassWithExecutor() {
this.es = Executors.newSingleThreadScheduledExecutor();
}
public void startScheduledTask() {
es.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
System.out.println("Printing this every minute");
}
}, 0, 3, TimeUnit.SECONDS);
}
}
}
By adding a shutdown hook that shuts down the ScheduledExecutor when the application context is closing, the JVM process now gets terminated after hitting the /shutdown endpoint:
#SpringBootApplication
public class AppSpringConfiguration {
public static void main(String[] args) {
SpringApplication.run(AppSpringConfiguration.class);
}
#Bean
public ClassWithExecutor ce() {
return new ClassWithExecutor();
}
#Bean
ShutdownAction sa() {
return new ShutdownAction(ce());
}
#PostConstruct
public void startScheduledTask() {
ce().startScheduledTask();
}
#RestController
public static class BusinessLogicController {
#RequestMapping(value = "/hi")
public String businessLogic() {
return "hi";
}
}
public static class ShutdownAction implements ApplicationListener<ContextClosedEvent> {
private ClassWithExecutor classWithExecutor;
ShutdownAction(ClassWithExecutor classWithExecutor) {
this.classWithExecutor = classWithExecutor;
}
#Override
public void onApplicationEvent(ContextClosedEvent event) {
classWithExecutor.shutdown();
}
}
public static class ClassWithExecutor {
ScheduledExecutorService es;
ClassWithExecutor() {
this.es = Executors.newSingleThreadScheduledExecutor();
}
public void startScheduledTask() {
es.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
System.out.println("Printing this every minute");
}
}, 0, 3, TimeUnit.SECONDS);
}
public void shutdown() {
es.shutdownNow();
}
}
}
You have something that prevents the JVM to exit besides your Spring Boot application. If you don't and you have a sample projet that demonstrates the problem, then please create an issue and we'll have a look.
Instead of using the shutdown endpoint, you can use the spring-boot-maven-plugin as of 1.3 that has a start and stop goals to be used in typical integration tests scenarios.
If you have a scheduled executor running you should specify destroy method:
#Bean(destroyMethod = "shutdown")

Resources