make async-await code style available in java just like csharp and es6

Overview

JAsync - the async-await pattern of Java

Maven Release

中文版

JAsync implements Async-Await pattern just like es in Java. It allows developers to write asynchronous code in a sequential fashion. It makes the developer's asynchronous programming experience as close as possible to the usual synchronous programming, including code style and debugging.

On the other hand, this framework separates the realization of the upper-level syntax tree conversion and the lower-level asynchronous workflow through a set of interfaces. This project focuses on the former, while the latter can be achieved by encapsulating existing asynchronous libraries, such as Reactor, RxJava, etc. The advantage of this is that this project can be seamlessly integrated with various asynchronous libraries that have been widely used in the community to produce an effect of 1+1>2.

Requirement

jdk >= 8

Examples

With JAsync

@RestController
@RequestMapping("/employees")
public class MyRestController {
    @Inject
    private EmployeeRepository employeeRepository;
    @Inject
    private SalaryRepository salaryRepository;

    // The standard JAsync async method must be annotated with the Async annotation, and return a JPromise object.
    @Async()
    private JPromise<Double> _getEmployeeTotalSalaryByDepartment(String department) {
        double money = 0.0;
        // A Mono object can be transformed to the JPromise object. So we get a Mono object first.
        Mono<List<Employee>> empsMono = employeeRepository.findEmployeeByDepartment(department);
        // Transformed the Mono object to the JPromise object.
        JPromise<List<Employee>> empsPromise = Promises.from(empsMono);
        // Use await just like es and c# to get the value of the JPromise without blocking the current thread.
        for (Employee employee : empsPromise.await()) {
            // The method findSalaryByEmployee also return a Mono object. We transform it to the JPromise just like above. And then await to get the result.
            Salary salary = Promises.from(salaryRepository.findSalaryByEmployee(employee.id)).await();
            money += salary.total;
        }
        // The async method must return a JPromise object, so we use just method to wrap the result to a JPromise.
        return JAsync.just(money);
    }

    // This is a normal webflux method.
    @GetMapping("/{department}/salary")
    public Mono<Double> getEmployeeTotalSalaryByDepartment(@PathVariable String department) { 
        // Use unwrap method to transform the JPromise object back to the Mono object.
        return _getEmployeeTotalSalaryByDepartment(department).unwrap(Mono.class);
    }
}

In this example, JAsync rewrite the code like XXX.await() to XXX.thenVoid(v -> { ... }) to making your methods non-blocking. With JAsync, you can not only enjoy the high throughput of non-blocking programming, but also avoid callback hell and counter-intuitive chained function calls.

What JAsync do.

@RestController
@RequestMapping("/employees")
public class MyRestController {
    @Inject
    private EmployeeRepository employeeRepository;
    @Inject
    private SalaryRepository salaryRepository;

    @Async()
    private JPromise<Double> _getEmployeeTotalSalaryByDepartment(String department) {
        double money = 0.0;
        DoubleReference moneyRef = new DoubleReference(money);
        Mono<List<Employee>> empsMono = employeeRepository.findEmployeeByDepartment(department);
        JPromise<List<Employee>> empsPromise = Promises.from(empsMono);
        return empsPromise.thenVoid(v0 -> JAsync.doForEachObject(v0, employee ->
                Promises.from(salaryRepository.findSalaryByEmployee(employee.id)).thenVoid(v1 -> {
                    moneyRef.addAndGet(v1.total);
                })
            ).thenVoid(() -> JAsync.doReturn(JAsync.just(moneyRef.getValue())))).catchReturn();
    }

    // This is a normal webflux method.
    @GetMapping("/{department}/salary")
    public Mono<Double> getEmployeeTotalSalaryByDepartment(@PathVariable String department) { 
        // Use unwrap method to transform the JPromise object back to the Mono object.
        return _getEmployeeTotalSalaryByDepartment(department).unwrap(Mono.class);
    }
}

How to use?

First, select a implementation library to the Maven dependency. Currently, only one implementation is available.

<dependency>
    <groupId>io.github.vipcxj</groupId>
    <artifactId>jasync-reactive</artifactId>
    <version>0.1.9</version>
</dependency>

This implementation uses the famous library Reactor. The JPromise object is a wrapper of Mono object. So the JPromise object can be created from a Mono object using static method io.github.vipcxj.jasync.reactive.Promises.from(reactor.core.publisher.Mono<T>). And the JPromise object can be converted back to the Mono object using instance method JPromise.unwrap.

Then add the core library to the Maven dependency.

<dependency>
    <groupId>io.github.vipcxj</groupId>
    <artifactId>jasync-core</artifactId>
    <version>0.1.9</version>
    <scope>provided</scope>
</dependency>

The core library is only need at compile stage, so here use the provided scope. Generally, the annotation processor should be discovered by jdk automatically. However, if something went wrong, jdk can not find the annotation processor, try this:

<plugins>
  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
      <annotationProcessorPaths>
        <path>
          <groupId>io.github.vipcxj</groupId>
          <artifactId>jasync-core</artifactId>
          <version>0.1.9</version>
        </path>
      </annotationProcessorPaths>
    </configuration>
  </plugin>
</plugins>

Note: If there exists annotationProcessorPaths configure, the dependency configure will not work.

Debug mode

JAsync support a debug mode. With debug mode on, JAsync will inject all useful variable to the current context, even they are not captured. As a result, When debugging, the developer can see all the variables in the monitor window just like debugging normal code.

For example, with debug mode off:

alt debug mode off

With debug mode on:

alt debug mode on

It can be seen that when the debug mode is turned on, all the defined variables can be found in the monitoring window.

About Lombok

If you are using Lombok, you should place the JAsync after the Lombok, just like this:

<plugins>
  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
      <annotationProcessorPaths>
         <path>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
         </path>
        <path>
          <groupId>io.github.vipcxj</groupId>
          <artifactId>jasync-core</artifactId>
          <version>0.1.9</version>
        </path>
      </annotationProcessorPaths>
    </configuration>
  </plugin>
</plugins>

Known Issues

  1. Not support new switch syntax introduced in java 17. It will be supported in the near future.
  2. Not support ejc (eclipse java compiler). I will try my best to support it. Currently, you can compile the project using maven or gradle, then debug using ejc.
Comments
  • [Urgent] Concurrency issue when a @Async method is first time accessed

    [Urgent] Concurrency issue when a @Async method is first time accessed

    I encounter an ConcurrentModificationException as shown below.

    It happens when a @ Async method is first time called by more than 1 threads. Say, if there's 2 thread concurrently access the method, one of them goes through, another thread will encounter ConcurrentModificationException.

    03-25 14:43:14 ERROR - 
    java.lang.RuntimeException: java.util.ConcurrentModificationException
    	at io.github.vipcxj.jasync.runtime.java8.helpers.IndyHelpers.createFunction(IndyHelpers.java:83) ~[jasync-runtime-0.1.9.jar:?]
    	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
    Assembly trace from producer [reactor.core.publisher.MonoError] :
    	reactor.core.publisher.Mono.error(Mono.java:314)
    	[SKIPPED...]
    Original Stack Trace:
    		at io.github.vipcxj.jasync.runtime.java8.helpers.IndyHelpers.createFunction(IndyHelpers.java:83) ~[jasync-runtime-0.1.9.jar:?]
    		at io.github.vipcxj.jasync.runtime.java8.helpers.IndyHelper.voidPromiseFunction(IndyHelper.java:139) ~[jasync-runtime-0.1.9.jar:?]
    		[SKIPPED...]
    		at java.lang.Thread.run(Thread.java:833) [?:?]
    Caused by: java.util.ConcurrentModificationException
    	at java.util.HashMap.computeIfAbsent(HashMap.java:1221) ~[?:?]
    	at io.github.vipcxj.jasync.runtime.java8.helpers.IndyHelpers.createFunction(IndyHelpers.java:51) ~[jasync-runtime-0.1.9.jar:?]
    	at io.github.vipcxj.jasync.runtime.java8.helpers.IndyHelper.voidPromiseFunction(IndyHelper.java:139) ~[jasync-runtime-0.1.9.jar:?]
    	[SKIPPED...]
    	at java.lang.Thread.run(Thread.java:833) [?:?]
    

    I look into it a bit, and I am pretty sure a lock is required at here.

    IndyHelpers.java (Original)

     protected  <T> T createFunction(
                Class<T> proxyType, String proxyMethodName, MethodType proxyMethodType,
                String implMethodName, MethodType implMethodType,
                boolean isStatic, Object thisObj, Object... args
        ) {
            try {
                final CallSite site = callSites.computeIfAbsent(implMethodName, k -> {
    
    

    Suggested change:

     protected  <T> T createFunction(
                Class<T> proxyType, String proxyMethodName, MethodType proxyMethodType,
                String implMethodName, MethodType implMethodType,
                boolean isStatic, Object thisObj, Object... args
        ) {
            try {
                // Get it without locking first
                CallSite site = callSites.get(implMethodName);
                if(site == null) {
                    synchronized {
                        //computeIfAbsent is still required here, as there may be multiple threads pass the if condition
                        site = callSites.computeIfAbsent(implMethodName, k -> {
    
    

    This issue is super important to fix. Would you please release a new version after fixing it? Thanks a lot!

    opened by knuclechan 9
  • Issue with uncaught exceptions

    Issue with uncaught exceptions

    If an exception is not caught and re-throw in the @Async method, the exception is gone.

    Let me use your example (simplified) to explain. I assume salaryRepository.findSalaryByDeparmentEmployee returns a mono. If the repository throws an exception (returned error mono) , I would expect the mono unwrapped at getEmployeeSalaryByDepartment is an error mono too, but it is a null value mono instead. The exception is gone.

    But if I catch and re-throw the error in the @Async method, then the unwrapped mono is an error mono.

    I think it is reasonable to assume that uncaught exception should be passed alone instead of swallowed. If there is implementation difficulty, I think it would be better to reminder others to catch exceptions in the @Async method.

    @RestController
    @RequestMapping("/employees")
    public class MyRestController {
    
        @Inject
        private SalaryRepository salaryRepository;
    
        @Async()
        private JPromise<Double> _getEmployeeTotalSalaryByDepartment(String department) {
            Salary salary = Promises.from(salaryRepository.findSalaryByDeparmentEmployee(department)).await();
            return JAsync.just(salary.total);
        }
    
        // This is a normal webflux method.
        @GetMapping("/{department}/salary")
        public Mono<Double> getEmployeeSalaryByDepartment(@PathVariable String department) { 
            // Use unwrap method to transform the JPromise object back to the Mono object.
            return _getEmployeeTotalSalaryByDepartment(department).unwrap(Mono.class);
        }
    }
    
    opened by knuclechan 3
  • Compilation error of for loop

    Compilation error of for loop

    Unable to handle an empty for loop

    Java Code

    @Async
    private JPromise<Boolean> method1(){
    	for(;;){
    		// do something
    	}
    	.....
    }
    

    Build Error

    [INFO] -------------------------------------------------------------
    [ERROR] COMPILATION ERROR : 
    [INFO] -------------------------------------------------------------
    [ERROR] SomeFile.java:[692] reference to doFor is ambiguous
      both method doFor(io.github.vipcxj.jasync.spec.functional.VoidPromiseSupplier,io.github.vipcxj.jasync.spec.functional.BooleanSupplier,io.github.vipcxj.jasync.spec.functional.VoidPromiseSupplier,io.github.vipcxj.jasync.spec.functional.VoidPromiseSupplier,java.lang.String) in io.github.vipcxj.jasync.spec.JAsync and method doFor(io.github.vipcxj.jasync.spec.functional.VoidPromiseSupplier,io.github.vipcxj.jasync.spec.functional.PromiseSupplier<java.lang.Boolean>,io.github.vipcxj.jasync.spec.functional.VoidPromiseSupplier,io.github.vipcxj.jasync.spec.functional.VoidPromiseSupplier,java.lang.String) in io.github.vipcxj.jasync.spec.JAsync match
    
    opened by knuclechan 2
  • Compilation error if method argument got re-assigned

    Compilation error if method argument got re-assigned

    Only happens when the argument is second or later. First argument is ok.

    Code

     	public Object test(){
     		return _test(1L,"").unwrap(Mono.class);
     	}
     	
     	@Async
     	private JPromise<String> _test(Long a, String b){
     		b = Promises.from(findById()).await();
     		
     		return Promises.from(b);
     	}
     	
     	private Mono<String> findById(){
     		return Mono.just("hi");
     	}
    

    Error

    [ERROR] cannot find symbol
      symbol:   variable tmp$$1642
      location: class TestController
    

    The following 2 cases has no issue.

    1. First argument get re-assigned
     	public Object test(){
     		return _test("").unwrap(Mono.class);
     	}
     	
     	@Async
     	private JPromise<String> _test(String b){
     		b = Promises.from(findById()).await();
     		
     		return Promises.from(b);
     	}
     	
     	private Mono<String> findById(){
     		return Mono.just("hi");
     	}
    
    1. No re-assignment. Directly returned
     	public Object test(){
     		return _test(1L,"").unwrap(Mono.class);
     	}
     	
     	@Async
     	private JPromise<String> _test(Long a, String b){
     		return Promises.from(findById()).await();
     	}
     	
     	private Mono<String> findById(){
     		return Mono.just("hi");
     	}
    
    opened by knuclechan 1
  • compile error

    compile error

        @Async(logResultTree = true)
        private static JPromise<Void> test(String command) {
            try {
                command = "对输入参数赋值,就挂了";
                JAsync.just().await();
            }
            catch( Exception e) {
    
            }
            return JAsync.just();
        }
    
    opened by qw623577789 1
  • compile error

    compile error

    @Async(logResultTree = true)
        public JPromise<Void> test() {
            String a = "定义a";
    
            try {
                a = "修改a";
                for (Long l : getList(a)) {
                    JAsync.just().await();
                }
            }
            catch(Exception error) {
    
            }
    
            return JAsync.just();
        }
    
        private ArrayList<Long> getList(String a) {
            return new ArrayList<Long>();
        }
    
    opened by qw623577789 1
  • ContinueException in 【for...continue...】

    ContinueException in 【for...continue...】

      @Async(logResultTree = true)
      public JPromise<Void> get() {
          ArrayList<Long> list = new ArrayList<>() {
              {
                  add(1l);
                  add(2l);
              }
          };
    
          for (Long l : list) {
              if (true) continue;   // throw io.github.vipcxj.jasync.spec.ContinueException
              JAsync.just().await();
          }
    
          return JAsync.just();
      }
    

    but the following example is successful

      @Async(logResultTree = true)
      public JPromise<Void> get() {
          ArrayList<Long> list = new ArrayList<>() {
              {
                  add(1l);
                  add(2l);
              }
          };
    
          for (Long l : list) {
              JAsync.just().await();
              if (true) continue;
          }
    
          return JAsync.just();
      }
    
    opened by qw623577789 1
  • compile fail when function params be used in lambda

    compile fail when function params be used in lambda

    raw code

      @Async(logResultTree = true)
      public <G> JPromise<Object> get(Object format) {
          JAsync.just().await();
          return JAsync.just(Optional.ofNullable(null).map(l -> format).get());
      }
    

    compiled code

    @Async(logResultTree = true)
    public <G>JPromise<Object> get(Object format) {
        return JAsync.just().thenVoid(indyHelper$$0.voidPromiseFunction("get$$tmp$$1", java.lang.invoke.MethodType.methodType(io.github.vipcxj.jasync.spec.JPromise.class, java.lang.Object.class))).catchReturn();
    }
    
    private <G>io.github.vipcxj.jasync.spec.JPromise<java.lang.Void> get$$tmp$$1(final java.lang.Object tmp$$0) throws java.lang.Throwable {
        ;
        return io.github.vipcxj.jasync.spec.JAsync.doReturn(JAsync.just(Optional.ofNullable(null).map((l)->format).get()));
    }
    

    loss the format params in sub function

    opened by qw623577789 1
  • compile fail when using generics params

    compile fail when using generics params

    image

    raw code

    @Async(logResultTree = true)
    public <G> JPromise<G> get(Class<G> format) {
        Long data = JAsync.just(1l).await();
        return JAsync.just(format.cast(data));
    }
    

    compiled code

    @Async(logResultTree = true)
    public <G> JPromise<Void> get(Class<G> format) {
      return JAsync
        .just(1L)
        .thenVoid(
          indyHelper$$0.voidPromiseFunction(
            "get$$tmp$$1",
            java.lang.invoke.MethodType.methodType(
              io.github.vipcxj.jasync.spec.JPromise.class,
              java.lang.Class.class,
              java.lang.Long.class
            ),
            format
          )
        )
        .catchReturn();
    }
    
    private io.github.vipcxj.jasync.spec.JPromise<java.lang.Void> get$$tmp$$1(
      final java.lang.Class<G> format,
      final java.lang.Long tmp$$0
    )
      throws java.lang.Throwable {
      Long data = tmp$$0;
      return io.github.vipcxj.jasync.spec.JAsync.doReturn(
        JAsync.just(format.cast(data))
      );
    }
    
    private static final io.github.vipcxj.jasync.runtime.java8.helpers.IndyHelpers indyHelpers$$0 = new io.github.vipcxj.jasync.runtime.java8.helpers.IndyHelpers(
      java.lang.invoke.MethodHandles.lookup()
    );
    private final io.github.vipcxj.jasync.runtime.java8.helpers.IndyHelper indyHelper$$0 = new io.github.vipcxj.jasync.runtime.java8.helpers.IndyHelper(
      indyHelpers$$0,
      this
    );
    

    loss the generics type in sub function image

    opened by qw623577789 1
  • java17模式匹配下if语句体编译报错

    java17模式匹配下if语句体编译报错

        @Async
        private JPromise<Void> simpleAwait() {
            Object obj = null;
            
            // 这种写法没问题
            if (obj instanceof String) {
                String stringObj = (String) obj;
                JAsync.just(null).await();
                System.out.println(stringObj);
            }
    
            // 这种写法编译报错
            if (obj instanceof String stringObj) {
                JAsync.just(null).await();
                System.out.println(stringObj);
            }
            return JAsync.just(null);
        }
    
        public static void main(String[] args) {
            App app = new App();
            System.out.println(app.simpleAwait().block());
        }
    

    报 System.out.println(stringObj); ^ 符号: 变量 stringObj 位置: 类 App

    opened by qw623577789 0
  • Not working on Android

    Not working on Android

    I marked my method @Async and didn't call it in a lambda or anonymous class but still got the following error:

    java.lang.UnsupportedOperationException: The method "JPromise#await" should be invoked in an async method. An async method is a method annotated with @JAsync and returning the JPromise object. The method should not be a lambda method or in an anonymous class
    	at io.github.vipcxj.jasync.reactive.ReactorPromise.await(ReactorPromise.java:450)
    

    Relevant code below:

    @Async
    public void loadAd(){
    	try{
    		AdManager.instance().interstitial().await();
    		...
    	}catch(Exception e){
    		e.printStackTrace();
    	}
    }
    
    public class AdManager extends com.customautosys.tuxfight.AdManager{
    	@Override
    	public JPromise<Void> interstitial(){
    		if(AndroidLauncher.getInstance().adView==null) return JAsync.error(new Exception("AdMob not loaded yet"));
    		return Promises.from(Mono.create(monoSink->AndroidLauncher.getInstance().runOnUiThread(()->InterstitialAd.load(
    			AndroidLauncher.getInstance(),
    			BuildConfig.DEBUG?"ca-app-pub-...":"ca-app-pub-...",
    			new AdRequest.Builder().build(),
    			new InterstitialAdLoadCallback(){
    				@Override
    				public void onAdLoaded(@NonNull InterstitialAd interstitialAd){
    					interstitialAd.show(AndroidLauncher.getInstance());
    					monoSink.success();
    				}
    
    				@Override
    				public void onAdFailedToLoad(@NonNull LoadAdError loadAdError){
    					monoSink.error(new Exception(loadAdError.getMessage()));
    				}
    			}
    		))));
    	}
    }
    
    opened by customautosys 4
  • Cannot load provider in a servlet setup with spring

    Cannot load provider in a servlet setup with spring

    Experience an error No provider of PromiseProvider found! when running servlet application with spring.

    I guess it may be related to the class loader hierarchy or class loading sequence.

    Currently I hack around this by adding a listener to the servlet

    	<listener>
    		<listener-class>ServletStartupListener</listener-class>
    	</listener>
    
    public class ServletStartupListener implements ServletContextListener {
    	
    	public void contextInitialized(ServletContextEvent sce) {
    		log.info("Init JAsync");
    		JAsync.just();
    	}
    	
    }
    

    I think one approach to solve this issue is to lazy load the provider instead of loading it in the static phase at JAsync.class

    opened by knuclechan 6
  • Micronaut + Reactor + JAsync doesn't compile

    Micronaut + Reactor + JAsync doesn't compile

    Hi,

    I tried to implement my first demo project with micronaut/reactor. Unfortunately this error pops up during compilation:

    Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project test: Fatal error compiling: java.lang.IllegalAccessError: class io.github.vipcxj.jasync.core.javac.JAsyncContext (in unnamed module @0x42ed89da) cannot access class com.sun.tools.javac.api.JavacTrees (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.api to unnamed module @0x42ed89da -> [Help 1]
    

    This is the sample project: https://github.com/mojo2012/async-test

    I hope you can help me fix this :-)

    cheers, matthias

    bug 
    opened by mojo2012 14
  • [Opinion solicitation] How should the api converting from third part object to Promise look like?

    [Opinion solicitation] How should the api converting from third part object to Promise look like?

    The implementation module which wrap the third part library such as Reactor or JxJava should be completely isolated from the core module. In other words, the implementation module should depend on core module, but the core module should not depend on the implementation module. This cause a problem, I don't know how should the api converting from third part object to Promise look like.

    • a: Use static method <T> Promise<T> JAsync.from(Object) in the core module. Obviously this is ugly and error-prone. But the fact that apis are aggregated together is an advantage.
    • b: Use static method <T> Promise<T> Promises.from(XXX<T> from) in the implementation module, where XXX may be Mono or Single or Future. This API makes perfect use of generics and looks more reliable but it doesn't make for a unified API.
    help wanted 
    opened by vipcxj 3
Owner
null
Async-Await support for Vertx using Project Loom

Vertx-Async-Await Async-Await support for Vertx using Project Loom. import static com.augustnagro.vertx.loom.AsyncAwait.async; import static com.augus

August Nagro 28 Oct 10, 2022
Library that allows tests written in Java to follow the BDD style introduced by RSpec and Jasmine.

J8Spec J8Spec is a library that allows tests written in Java to follow the BDD style introduced by RSpec and Jasmine. More details here: j8spec.github

J8Spec 45 Feb 17, 2022
A BDD-style test runner for Java 8. Inspired by Jasmine, RSpec, and Cucumber.

Spectrum A colorful BDD-style test runner for Java Spectrum is inspired by the behavior-driven testing frameworks Jasmine and RSpec, bringing their ex

Greg Haskins 143 Nov 22, 2022
Consume an async api (with callback) from sync endpoint using vert.x

vertx-async-to-sync Problem statement Suppose we have two services - A and B. In a trivial and everyday scenario, client makes request to A. A then do

Tahniat Ashraf Priyam 12 Oct 19, 2022
Serenity BDD is a test automation library designed to make writing automated acceptance tests easier, and more fun.

That feeling you get when you know you can trust your tests Serenity BDD is a library designed to make writing automated acceptance tests easier, and

Serenity BDD 654 Dec 28, 2022
This is Yoink Inc's Rat (Doesnt work if u want u can make it work and pull request this)

Yoink-RAT This is Yoink Inc's Rat (Doesnt work if u want u can make it work and pull request this) Why cuz How do i use it just put your webhook in it

INZO_Technologies 5 Dec 14, 2022
A TestNG like dataprovider runner for JUnit with many additional features

junit-dataprovider Have a look to this repositories Wiki pages for documenation, usage examples and further information. Table of contents Home What i

TNG Technology Consulting GmbH 237 Sep 7, 2022
Advanced Java library for integration testing, mocking, faking, and code coverage

Codebase for JMockit 1.x releases - Documentation - Release notes How to build the project: use JDK 1.8 or newer use Maven 3.6.0 or newer; the followi

The JMockit Testing Toolkit 439 Dec 9, 2022
PowerMock is a Java framework that allows you to unit test code normally regarded as untestable.

Writing unit tests can be hard and sometimes good design has to be sacrificed for the sole purpose of testability. Often testability corresponds to go

PowerMock 3.9k Dec 28, 2022
PowerMock is a Java framework that allows you to unit test code normally regarded as untestable.

Writing unit tests can be hard and sometimes good design has to be sacrificed for the sole purpose of testability. Often testability corresponds to go

PowerMock 3.9k Dec 28, 2022
Isolated MinIO container management for Java code testing

TestContainers for MinIO MinIO support for the test containers project. Installation Unfortunately, TestContainers for MinIO is not available in any p

Olsi Qose 3 Sep 30, 2022
CodeSheriff is a simple library that helps you in writing JUnit tests that check the quality of your code

CodeSheriff is a simple library that helps you in writing JUnit tests that check the quality of your code. For example, CodeSheriff may fail because you have methods in your code that have more than X lines of code, or that have complexity greater than Y.

Maurício Aniche 62 Feb 10, 2022
PGdP-Tests-WS21/22 is a student-created repository used to share code tests.

PGdP-Tests-WS21-22 PGdP-Tests-WS21/22 is a student-created repository used to share code tests. Important Note: In the near future, most exercises wil

Jonas Ladner 56 Dec 2, 2022
Web automation example code of tests running parallely

Don't forget to give a ⭐ to make the project popular. ❓ What is this Repository about? This repo contains example code to run a single test parallely

Mohammad Faisal Khatri 1 Apr 3, 2022
JVM version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.

pact-jvm JVM implementation of the consumer driven contract library pact. From the Ruby Pact website: Define a pact between service consumers and prov

Pact Foundation 962 Dec 31, 2022
Roman Beskrovnyi 248 Dec 21, 2022
A Java architecture test library, to specify and assert architecture rules in plain Java

ArchUnit is a free, simple and extensible library for checking the architecture of your Java code. That is, ArchUnit can check dependencies between pa

TNG Technology Consulting GmbH 2.5k Jan 2, 2023
Never debug a test again: Detailed failure reports and hassle free assertions for Java tests - Power Asserts for Java

Scott Test Reporter for Maven and Gradle Get extremely detailed failure messages for your tests without assertion libraries, additional configuration

Dávid Csákvári 133 Nov 17, 2022
IntelliJ IDEA and JUnit: Writing, Finding, and Running Tests

IntelliJ IDEA and JUnit: Writing, Finding, and Running Tests ?? Webinar https://blog.jetbrains.com/idea/2021/11/live-stream-recording-intellij-idea-an

Christian Stein 11 Jul 23, 2022