Squaretest
  for IntelliJ IDEA

Java Unit Test Generator for IntelliJ IDEA

Automatically generate unit tests for your Java classes with the Squaretest plugin for IntelliJ IDEA.
Create a Test Class for a Java Class

Generate a Test Class for a Java Class with One Action

Select Squaretest | Generate Test (Alt+Insert+Generate Test) to generate a test class in either Java (1.8+) or Groovy. More...

The Generated Test Class Contains Appropriate Boilerplate Code

Squaretest automatically generates the following based on your source class:
  • Code to construct the source class and initialize its dependencies, in many cases
  • A test method for each public and package-local method in the source class, containing
    • Local variables for arguments required by the method
    • Mockito stubs; i.e. when() and doAnswer() statements
    • Code to invoke the method
    • An assertEquals() call or Groovy assertion statement
    • Mockito verify() statements
    • Code to initialize data transfer object (DTO) beans used in the above
  • Test methods for alternate flows, including cases where:
    • Dependency methods throw exceptions
    • Dependency methods return either null or absent values; e.g. Optional.absent()
    • Dependency methods return empty values; e.g. Collections.emptyList()
    • Dependency methods return failure values; e.g. CompletableFuture.failedFuture(exception)
    • Dependency methods return broken I/O values; e.g. new BrokenInputStream()
    • Dependency methods return empty I/O values; e.g. InputStream.nullInputStream()
    • Method parameters contain broken I/O values; e.g. new BrokenInputStream()

Advanced Pattern Recognition

Squaretest uses pattern recognition to generate alternate flow tests based on dependency method return values. Squaretest generates special tests for datatypes nested within the following types:
  • Functional Wrappers
  • Response Wrappers
  • Listenable Future
  • Completable Future
  • Custom Optional Types
  • See Examples...
Squaretest also generates tests for return values that contain I/O types like the S3Object and the ResponseInputStream from the AWS SDKs.

Reads the Javadocs

Squaretest reads the Javadocs for the dependency methods the source class interacts with. This enables Squaretest to create tests for cases where:
  • The dependency methods throw the exceptions declared in the @throws tags
  • The dependency methods return null, in some cases
    • Squaretest looks for annotations indicating whether or not a method can return null.
    • Squaretest uses very basic Natural Language Processing (NLP) to determine if the Javadocs indicate a method can return null.
This enables Squaretest to create tests for cases the developer may have missed due to not reading the Javadocs.

Choose Which Dependencies Should Be Mocked

Select Squaretest | Generate Test - Confirm Mocks (Alt+Insert+Generate Test - Confirm Mocks) to choose which dependencies should be mocked before creating the test class.

Use a Velocity Template to Configure How the Test Classes Are Generated

All aspects of the generated test classes are determined by an Apache Velocity template. You can use one of the default templates included with Squaretest or create your own template. More...

Includes Default Velocity Templates for Common Test Frameworks

Squaretest includes default Velocity templates for both Java and Groovy for the following test frameworks and mocking frameworks.
  • JUnit4 with Mockito
  • JUnit4 with Mockito and AssertJ
  • JUnit4 with Spring and Mockito
  • JUnit4 with Spring, Mockito and AssertJ
  • JUnit5 with Mockito
  • JUnit5 with Mockito and AssertJ
  • JUnit5 with Spring and Mockito
  • JUnit5 with Spring, Mockito and AssertJ
  • TestNG with Mockito
  • Robolectric3+ with Mockito
  • AndroidJUnit4 with Mockito

Detects Design Patterns in the Source Class

All templates included with Squaretest detect and handle the following design patterns in the source class.
  • Class with dependencies provided in the constructor (the standard Java component)
  • Class with private, dependency-annotated fields (fields annotated with @Inject or @Autowired)
  • Class with package-local, dependency-annotated fields (common in Android apps using Dagger or Guice).
  • Class with static creator methods like parse(..) or from(..) but no package-visible constructor; i.e. the sealed abstract class and similar patterns
  • Abstract classes in general
  • Class containing only static methods; i.e. the Utils classes.
  • Singletons (traditional and enum)
  • Enums in general
  • Android activity (Robolectric3 and AndroidJUnit4 templates only)
  • Spring controllers (Spring templates only)
  • More Examples...

Initializes Data Transfer Objects

Squaretest initializes data transfer objects (DTOs) returned by dependency methods as well as those used in method parameters. Squaretest recursively initializes DTOs using the following patterns.
  • Classes with data provided via the constructor.
  • Beans with data provided via setter methods.
  • JAXB beans with list properties (where data is provided by adding items to the list returned by the corresponding getter method).
  • Classes generated by Protobuf-3
  • Request and Response classes used in the AWS SDK V1 and V2.
  • Classes initialized by calling static creator methods; e.g. from(..) or of(..).

Generates Code Based on Dependency Method Return Values

Squaretest generates code based on the values returned by dependency methods the source methods interact with. This includes the following.
  • Verify statements to ensure Closeables returned by dependency methods are closed.
  • Alternate flow tests for some AWS SDK APIs that return absent or empty values.
  • Alternate flow tests for dependency methods that return objects containing I/O values; e.g. the AWS SDK S3 APIs for retrieving objects.

Default Templates Contain Quick Settings

All templates included with Squaretest have Quick Settings, or variables set at the top of the file that can be used to set code style and other settings. The Quick Settings include the following options.
  • Use special prefixes for test class members containing dependencies and/or mocks
  • Use special prefixes for local fields containing test method parameters and/or mocks
  • Customize the name of the member or local field used to store the instance of the source class.
  • Use the JUnit5 Mockito Extension or the JUnit4 Mockito Runner
  • Use static imports for initMocks and related methods
  • Use mocks for mockable parameters whose names end in listener or callback
  • Use custom initialization expressions for dependencies and test method arguments of certain types. More...

Default Values for Common Types

Squaretest uses default values for commonly-used types that developers don't usually mock; e.g. dependencies and local fields of type List will be set to either Arrays.asList() or List.of() instead of a mock or null. Squaretest recognizes 150+ default types from the following libraries.
  • The JDK 8+
  • Apache Commons Lang 2 and 3
  • Google Guava
  • RxJava
  • Retrofit
  • AWS SDK V1 and V2
Squaretest also selects default values based on the libraries present on the test classpath; e.g. dependencies and local fields of type Executor will use MoreExecutors.directExecutor() from Google Guava if it's available on the test classpath.

Similarly, Squaretest generates doAnswer() statements for dependency interactions that take in Callables or Runnables; these statements invoke the call() or run() methods and return either a CompletableFuture or ListenableFuture (when applicable).

Configurable Project-Level and Module-Level Settings

Create a Test Method

Add a Test Method to your Test Class

Start typing the name of the test method you want to create to see code completion suggestions based on the methods in your source class; then select one of the suggested methods to create it.

The Test Method Contains Appropriate Boilerplate Code

The generated test method contains:
  • Local variables for arguments required by the method
  • Mockito stubs; i.e. when(), doAnswer() and doThrow() statements
  • Code to invoke the method
  • An assertEquals() call or groovy assertion statement
  • Mockito verify() statements
Create Multiple Test Methods

Add Multiple Test Methods To Your Test Class

Select Squaretest | Generate Test Methods (Alt+Insert+Generate Test Methods) to see a list of test methods to add to your test class.

The list includes tests for alternate flows for each source method; e.g. if a source method calls foo.bar(), and bar() can throw an IOException, Squaretest will suggest a method called testMethodName_FooThrowsIOException(); the generated test method will stub foo to throw an IOException when bar() called.

The Test Methods Contains Appropriate Boilerplate Code

The generated test method contains:
  • Local variables for arguments required by the method
  • Mockito stubs; i.e. when(), doAnswer() and doThrow() statements
  • Code to invoke the method
  • An assertEquals() call or groovy assertion statement
  • Mockito verify() statements

User Guide

Install
You can install the Squaretest plugin from the IntelliJ plugin repository by following the instructions below.
  1. Go to File | Settings | Plugins | Browse Repositories...
  2. Enter Squaretest in the search bar at the top
  3. Select the Squaretest plugin, then click the Install button on the right.
You can try Squaretest for free for 30 days.
Getting Started
The best way to get started with Squaretest is to use it to create a test by following the instructions below.
  1. Open a file that you want to create unit tests for
  2. Do one of the following
    • Press ctrl+alt+k on Windows/Linux or cmd+shift+L on OS X.
    • Choose Squaretest | Generate Test from the toolbar
  3. Follow the instructions on the Configure Squaretest Module Settings dialog.
    The options are as follows.
    • Test Language the language to create your tests in (either Java or Groovy)
    • Template the Apache Velocity template used to create your tests; the templates are named according to the test-runner and mocking framework they use.
    • Test Sources Root the directory in which Squaretest will create your tests (and any package directories required) for this module.
    • Promote Test Language and Template to Project Settings whether or not Squaretest will save the above Test Language and Template in the Project Settings or the Module Settings; the default setting works best for most users.
    • Module Configuration whether or not Squaretest should try to configure the settings for your other modules automatically when they are needed or show this dialog every time; the default setting works best for most users. See Module Configuration for more details.
    Clicking OK will save these settings and create your test class. You can modify these settings later in the Squaretest Settings Menu described in the next section.
Settings
The Squaretest settings can be changed by doing the following.
  1. Go to File | Settings
    • Mac OS X Users: IntelliJ IDEA | Preferences
  2. Click the Squaretest option shown near the bottom of the list on the left.
The application, project and module-level settings are as follows.
Application Settings
These settings apply to the Squaretest application; i.e. all projects. The options are as follows.
  • Open the Test File specifies which editor window Squaretest should open the test class in; options are:
    • In the active editor window
    • In the next editor window if one is available
      Squaretest will open the test class in the editor window next to the active editor window if one is available; otherwise, it will open the test class in the active editor window.
    • In the next editor window, creating one if needed
      Squaretest will open the test class in the editor window next to the active editor window if one is available; otherwise, it will create a new editor window by splitting the active editor window vertically and open the test class in the new window.
  • Template Manager this shows a dialog allowing you to delete or rename any templates you've created.
Project Settings
The Project Settings apply to an IntelliJ Project. They are as follows.
  • Test Language the language to create your tests in (either Java or Groovy)
  • Template the Apache Velocity template used to create your tests.
  • Module Configuration
    • Automatically configure when possible
      Squaretest will automatically configure the Module Settings the first time they are needed if the Project Settings contain a template and one of the following is true.
      • The module contains exactly one test-sources root, and the test-sources root contains source files matching the template-language (Java or Groovy) in the Project Settings (the most common scenario).
      • The module contains exactly one Groovy test-sources root and the Project Settings contain a Groovy-template.
      • The module contains no test-sources roots and its dependent modules collectively contains exactly one test-sources root and that test-sources root contains source files matching the template-language in the Project Settings.
    • Always ask to configure module settings
      Squaretest will always prompt the user to configure settings the first time a test is generated for a module.
Module Settings
The Module Settings apply to a specific module. They are as follows.
  • Test Language the language to create your tests in (inherited from the Project Settings by default)
  • Template the template used to create your tests (inherited from the Project Settings by default)
  • Test Sources Root the directory Squaretest will create your tests (and any package directories required) for this module
Keyboard Shortcut
The Squaretest keyboard shortcut can be changed by doing the following.
  1. Go to File | Settings | Keymap
  2. Expand the Plugins folder and then the Squaretest folder
  3. Double-click the Generate Test item and select Add Keyboard Shortcut.
  4. Set the desired shortcut, then click OK, then OK again.
Create Your Own Template
You can create your own template to use to generate tests by doing the following.
  1. Select a template in either the Project Settings or the Module Settings.
  2. Make changes to the template code shown in the editor (see the image below)
    Squaretest JUnit Generator Settings Menu
  3. Enter a name for your template in the textbox next to the Save Template As button.
  4. Click Save Template As, then OK
Delete or Rename Templates
You can delete or rename the templates you've created by clicking Manage All Templates in the Application Settings.
Template Best Practices
The Velocity templates included with Squaretest are organized into 4 parts. Most developers will only need to modify the first 2 parts to update the template to match their code style and conventions. The parts are described below in the order in which they appear in the template code.
1. Quick Settings
The first section of the template contains Quick Settings, or variables that configure common code style settings and other aspects of the test class that are applied throughout the template code. See Quick Settings for details about each setting.
2. Test Class Rendering Code
This is the code that renders the test class, including the package declaration, import statements and class definition. You can modify this code to match the conventions used in your tests; e.g. add @RunWith annotations, make the test class extend a common base class in your project or module, add comments between the mock variable declarations and the non-mock variable declarations, etc. See Template Data Model for the list of variables available to the test class rendering code.
3. Helper Macros
This contains macros used to render parts of the test class; e.g. renderTestMethods($methods). These macros are invoked in the Test Class Rendering Code and can be modified to change how parts of the test class are created.
4. InitializeTemplateDataModel Macro
The initializeTemplateDataModel macro configures the data model based on the archetype of the source class and the Quick Settings. This macro is called immediately after the Quick Settings section and sets global variables describing how the test class should be rendered. The global variables are set based on the source class's constructors, fields, methods, annotations and other factors. The variables set by the macro are described here and may be used in the Test Class Rendering Code and the Helper Macros.

Power users can modify this macro and its helper macros (defined below the macro) to add or change variables in the data model to accommodate their use cases.

Users should follow the convention of using the initializeTemplateDataModel macro to add or modify variables in the data model, then update the Test Class Rendering Code to check for the new variables and change the output accordingly. This keeps the logic to configure the data model separate from the test class rendering code and allows both to grow in complexity without becoming unmaintainable.
Formatting Tips
Squaretest is designed to allow users to make changes to the template without worrying about formatting. To accomplish this, Squaretest automatically performs several code-cleanup tasks on the generated test class, described here. In general, users should follow the guidelines below.
  • Don't worry about organizing the import-statements
    • These will be organized according to your IDE code style settings in the code-cleanup.
  • Use the fully qualified, canonical text when declaring members and variables; e.g. Variable.type.canonicalText.
    • These will be shortened automatically in the code-cleanup.
    • Using fully qualified, canonical text simplifies declaring variables with generic types.
  • Don't worry about having extra newlines (more than 1 empty-line) between sections of the test class; those are removed in the code-cleanup.
  • Don't worry about over-indenting the Java code or Groovy code in your templates
    • The test class will be formatted according to your IDE code style settings in the code-cleanup.
Advanced Template Editing
Users making significant changes to the templates may wish to use a different editor. The following editors work well.
IntelliJ IDEA Ultimate
The IntelliJ IDEA Ultimate IDE includes a good Velocity editor plugin and comes with a free trial. Squaretest also implements the velocity.globalVariableProvider extension point in the Velocity plugin to provide limited code-completion suggestions and javadocs for some of the template variables. To use the editor, simply use the Squaretest plugin in IntelliJ IDEA Ultimate. Squaretest will automatically use the editor provided by the Velocity plugin in the Settings menu and Configure Squaretest Module Settings dialog.
Other Editors
Squaretest stores the user-created templates in the IntelliJ Template Manager, which stores them in files on the file system. You can edit these files using your editor of choice. Please do not rename them. Also note that you will need to restart IntelliJ IDEA after changing the files. The template files are stored in the following locations.
OS Path
Windows <SYSTEM DRIVE>\Users\<USER ACCOUNT NAME>\.<PRODUCT><VERSION>\config\fileTemplates
Mac OS X ~/Library/Preferences/.<PRODUCT><VERSION>/fileTemplates
Linux ~/.<PRODUCT><VERSION>/fileTemplates

Template API

The Template API is the data model available to the Velocity template used to create the test class. The Velocity variables that make up the data model are described in the sections below.
Quick Settings
The Quick Settings are variables set at the top of the default templates that can be used to set code style and other settings. This section describes the Quick Settings available in the default templates included with Squaretest.

Name Type Description
$dependencyMemberNamePrefix String An optional prefix used for test class members that contain dependencies for the source class. If set to "", the template code will use your IDE code style settings instead.
$mockDependencyMemberNamePrefix String Similar to $dependencyMemberNamePrefix but only applies to test class members containing mocks.
$parameterLocalFieldNamePrefix String An optional prefix for local fields that contain arguments for test methods. If set to "", the template code will use your IDE code style settings instead.
$mockParameterLocalFieldNamePrefix String Similar to $parameterLocalFieldNamePrefix but only applies to local fields containing mocks.
$sourceClass.testClassMemberName String The name of the member used to store an instance of the source class. The default value is determined by the IDE code style settings.
$sourceClass.testClassLocalFieldName String This is similar to $sourceClass.testClassMemberName, but is used when storing an instance of source class in a local field in the test class.
$shouldUseMockitoExtension boolean Indicates whether the template should use the JUnit5 mockito extension (in JUnit5 templates) or the JUnit4 mockito runner (JUnit4 templates). By default this is set to true if the extension or runner is present on the test classpath and false otherwise.
$maxRecursiveBeanInitDepth int Sets the maximum level at which Bean DTOs within other Bean DTOs will be initialized.
$maxNumberOfBeanSettersToCallPerClass int Sets the maximum number of setter methods to call on an individual class when initializing a bean.
$maxNumberOfBeanSettersToCall int Sets the maximum number of setter methods to call when initializing a top-level bean.
$useStaticImportForInitMocks boolean This specifies whether or not MockitoAnnotations.initMocks and related methods should be imported with static imports.
$useMocksForListenerAndCallbackParameters boolean If set to true, the template will use mocks for any mockable method parameter whose name ends in "listener" or "callback", ignoring case.
$generateStubsAndVerifyStatements boolean If set to true, the template will generate Mockito stubs and verify statements in the test methods.
$initExpressionOverrides Map<String, Map> This sets custom initialization expressions for dependencies and method parameters of certain types. The key is the canonical name of the type. The value is a Map containing the following keys and values.
Key Value
initExpression A String containing a Java expression that evaluates to an instance of the type.
importsRequired An optional List<String> containing the import lines required for the initExpression.
shouldStoreInReference A boolean indicating whether or not the value of the initExpression should be stored in a reference (local variable or test class member) or used inline when needed.
The example below specifies that dependencies and method parameters of type android.content.Context should have value: RuntimeEnvironment.application and that the expression RuntimeEnvironment.application should be used inline wherever the dependency is needed rather than stored in a reference.
#set($initExpressionOverrides["android.content.Context"] = {
  "initExpression" : "RuntimeEnvironment.application",
  "importsRequired" :  ["import org.robolectric.RuntimeEnvironment;"],
  "shouldStoreInReference" : false })
              
Data Model
Squaretest converts the source class (the class for which the test is being generated) into the following Data Model available to the Velocity template code.
Template Variables
Name Type Description
$sourceClass SourceClass Describes the class for which the test is being generated
$importsRequired Set<String> Imports required by various components in the SourceClass
$shouldAskToConfirmSettings boolean Indicates whether the user invoked the "Generate Test" action or the "Generate Test - Confirm Mocks" action.
$AltInfo AltInfoFactory The AltInfoFactory class provides methods for creating the AltInfo objects that describe an alternate flow test case that should be rendered.
$ClassUtils ClassUtils The ClassUtils class provides methods for obtaining information about classes on test classpath; i.e. accessible from the sources root in which the test class will be created.
$CodeStyleUtils CodeStyleUtils The CodeStyleUtils class provides methods for obtaining recommended names for fields based on the IDE code style settings.
$FluentList FluentListFactory Provides a method for creating an empty FluentList<T>; e.g. $FluentList.of().
$ListUtils ListUtils The ListUtils class provides methods for operating on lists.
$MutableBoolean MutableBooleanFactory The MutableBooleanFactory class provides methods for creating MutableBooleans.
$MutableInt MutableIntFactory The MutableIntFactory class provides methods for creating MutableInts.
$MutableObject MutableObjectFactory The MutableObjectFactory class provides methods for creating MutableObjects.
$MutableString MutableStringFactory The MutableStringFactory class provides methods for creating MutableObject<String> instances.
$Newline String This contains the newline character.
$Null null This contains null.
$StringUtils StringUtils Contains everything in Apache Commons Lang 3 StringUtils, plus a few extra methods.
$UiUtils UiUtils The UiUtils class provides a method to show a dialog asking the user to confirm settings determined by the template; e.g. confirm which dependencies should be mocked.
Template Variables Added by the InitializeTemplateDataModel() Macro
The #initializeTemplateDataModel() macro, defined in the template code, is invoked after the Quick Settings section in the default templates and sets several variables used in the rendering logic. These variables are set based on the Quick Settings and the code patterns used in the $sourceClass. The variables are described below.

Name Type Description
$androidActivity
boolean This is only set in the Robolectric3 and AndroidJUnit4 templates. This is true if the $sourceClass is an Android Activity.
$dependencies FluentList<Variable> Contains all fields the test class should provide for the instance of $sourceClass
$hasOpenMocksMethod boolean true if MockitoAnnotations.openMocks(..) exists on the test classpath.
$initMocksMethodName String Contains "openMocks" if $hasOpenMocksMethod is true; otherwise, this contains "initMocks".
$memberFields FluentList<Variable> A subset of $dependencies containing all fields that should be stored in members in the test class.
$mockMemberFields FluentList<Variable> A subset of $memberFields containing only fields that should be mocked.
$mocksNeeded boolean true if $sourceClass has at least one dependency that should be mocked.
$nonMockMemberFields FluentList<Variable> A subset of $memberFields containing all fields that should not be mocked.
$shouldCreateTestsForInstanceMethods boolean a boolean indicating whether or not test should be created for the instance methods in the $sourceClass.
$shouldSetPackageLocalFields boolean a boolean indicating whether or not the test class should provide dependencies to the $sourceClass by setting package-local fields.
$shouldUseInjectMocks boolean a boolean indicating whether or not @InjectMocks should be used to provide dependencies to the instance of the $sourceClass.
$sourceClassMemberNeeded boolean a boolean indicating whether or not an instance of $sourceClass should be created and stored in a member of the test class.
Spring Variables Added by the InitializeTemplateDataModel() Macro
The #initializeTemplateDataModel() macro, defined in the Spring templates adds additional variables that are used in the rendering logic. These are described below.

Name Type Description
$allModelAttributeProviderMethods
FluentList<Method> The list of all model attribute provider methods in the source class and its super classes.
$basePath
String The base uri path for the spring controller under test, or '' if one is not set.
$controllerMethods
FluentList<Method> The list of controller methods in the source class.
$hasClassSecurityAnnotations
boolean This is true if the $sourceClass has Spring security annotations.
$mockMvcMemberName
String A String containing the name to use for the MockMvc member field.
$modelAttributeProviderMethodDIs
FluentList<DI> The list of dependency interactions in all of the model attribute provider methods in the source class.
$modelAttributeProviderMethods
FluentList<Method> The list of model attribute provider methods in the source class.
$restController
boolean This is true if the $sourceClass is a Spring rest controller.
$springController
boolean This is true if the $sourceClass is a Spring controller.
Template Variable Types
SourceClass
Property Name Type Description
abstract boolean True if source class is abstract.
abstractClassBody String Contains the body of an anonymous instance of the abstract class that contains stubs for all of the abstract methods.
allSuperClasses FluentList<SourceClass> Contains all super classes and interfaces of this source class.
allSuperTypeNames FluentList<String> Contains the canonical names of all super classes and interfaces of this class.
annotations FluentList<Annotation> Contains the annotations on the source class.
constructors FluentList<Constructor> Contains all constructors in the class, including the default constructor provided by the java language spec if applicable.
constructorsAnnotatedWith(
String... annotationNames)
FluentList<Constructor> Returns all constructors annotated with at least one of the provided annotations. The list: annotationNames can include simple and canonical names. Any value containing a dot (.) will be treated as a canonical name.
dtoBean boolean True if source class is a data transfer object (DTO) bean.
dtoBeanWithInputIoProperty boolean True if the source class is a data transfer object (DTO) bean that contains an Input I/O property; e.g. S3Object in the AWS SDK V1 API.
enum boolean True if source class is an enum.
enumFirstValue String Contains the first value in the enum if source class is an enum; otherwise, returns null.
enumValues FluentList<String> Returns the values in the enum if source class is an enum; otherwise, returns the empty list.
fields FluentList<ClassMember> Contains all fields (static and instance) in the source class
fieldsAnnotatedWith(
String... annotationNames)
FluentList<ClassMember> Returns all fields annotated with at least one of the provided annotations. The list: annotationNames can include simple and canonical names. Any value containing a dot (.) will be treated as a canonical name.
hasAnnotation(
List<String> annotationNames)
boolean Returns whether or not this class is annotated with one of the provided annotation names. Annotation names can include simple and canonical names..
hasAnnotation(
String... annotationNames)
boolean Returns whether or not this class is annotated with one of the provided annotation names. Annotation names can include simple and canonical names..
hasAnnotationWithPrefix(
List<String> prefixes)
boolean Returns whether or not this class has an annotation that starts with one of the provided prefixes.
hasAnnotationWithPrefix(
String... prefixes)
boolean Returns whether or not this class has an annotation that starts with one of the provided prefixes.
hasGenerics boolean True if source class has one or more type parameters.
instanceFields FluentList<ClassMember> Contains all instance fields in source class.
instanceMethods FluentList<Method> All instance methods in the source class.
is(String
  canonicalName)
boolean Returns true if this class is an instance of the provided canonical name.
isAll(List<String>
  canonicalNames)
boolean Returns true if this class is an instance of all of the provided canonical names.
isAll(String...
  canonicalNames)
boolean Returns true if this class is an instance of all of the provided canonical names.
isAny(List<String>
  canonicalNames)
boolean Returns true if this class is an instance of one of the provided canonical names.
isAny(String...
  canonicalNames)
boolean Returns true if this class is an instance of one of the provided canonical names.
methods FluentList<Method> All methods in the source class
methodsAnnotatedWith(
String... annotationNames)
FluentList<Method> Returns all methods annotated with at least one of the provided annotations. The list: annotationNames can include simple and canonical names. Any value containing a dot (.) will be treated as a canonical name.
name String Contains the name of the source class.
packageLocalConstructors FluentList<Constructor> All package-local constructors in source class.
packageLocalInstanceFields FluentList<ClassMember> Contains all package-local instance fields in source class.
packageLocalInstanceMethods FluentList<Method> All package-local instance methods in the source class
packageLocalStaticFields FluentList<ClassMember> Contains all package-local static fields in source class.
packageLocalStaticMethods FluentList<Method> All package local static methods in the source class
packageName String Contains the package name from the package declaration statement in source class.
packageVisibleStaticCreatorMethods FluentList<Method> Contains all static methods that return an instance of source class and have package-local access or higher.
preferredConstructor Constructor Mutable field that, by default, contains longest constructor (constructor with the most arguments) with at least package-local access or higher (Public, Protected or Package Local).
preferredInitSetters FluentList<Method> Contains the list of preferred setters to use to initialize the source class. For most cases, this will be the list of simpleSetters.
privateConstructors FluentList<Constructor> All private constructors in source class
privateInstanceFields FluentList<ClassMember> Contains all private instance fields in source class.
privateInstanceMethods FluentList<Method> All private instance methods in the source class
privateStaticFields FluentList<ClassMember> Contains all private static fields in source class.
privateStaticMethods FluentList<Method> All private static methods in the source class
protectedConstructors FluentList<Constructor> All protected constructors in source class.
protectedInstanceFields FluentList<ClassMember> Contains all protected instance fields in source class.
protectedInstanceMethods FluentList<Method> All protected instance methods in the source class
protectedStaticFields FluentList<ClassMember> Contains all protected static fields in source class.
protectedStaticMethods FluentList<Method> All protected static methods in the source class
publicConstructors FluentList<Constructor> All public constructors in the source class, including the default constructor provided by the java language spec if applicable.
publicInstanceFields FluentList<ClassMember> Contains all public instance fields in source class.
publicInstanceMethods FluentList<Method> All public instance methods in the source class
publicStaticFields FluentList<ClassMember> Contains all public static fields in source class.
publicStaticMethods FluentList<Method> All public static methods in the source class
sealed boolean True if source class is sealed.
simpleGetters FluentList<Method> Simple getter methods in the source class.
simpleSetters FluentList<Method> Simple setter methods in the source class.
singleton boolean True if source class is a singleton; false otherwise.
singletonAccessExpression String The expression needed to access the instance of the singleton if source class is a singleton; e.g. getInstance(), instance(), INSTANCE; null otherwise. 
staticFields FluentList<ClassMember> Contains all static fields in source class.
staticMethods FluentList<Method> All static methods in the source class
testClassLocalFieldName String Mutable field containing the name of the local field used to store an instance of the source class. The default value is determined by the IDE code style settings.
testClassMemberName String Mutable field containing the name of the member used to store an instance of the source class. The default value is determined by the IDE code style settings.
type Type Contains the type of the source class.
Method
Property Name Type Description
abstract boolean True if the method is abstract.
accessLevel String Returns a String representing the access level for this method. Possible values are private, protected, packagePrivate, public.
annotations FluentList<Annotation> Contains the annotations on the method.
constructor boolean True if the method is a constructor.
declaredExceptions FluentList<Exception> The list of exceptions the method declares to be thrown.
dependencyInteractions FluentList<DI> All dependency interactions (field, method) pairs this method interacts with in the source class. This includes dependency interactions in this method's body as well as interactions in other methods in the same source class that are called from this method's body.
deprecated boolean True if the method is deprecated.
getSuperMethodParametersAtIndex(
int index)
FluentList<Variable> Returns all super method parameters at the specified index.
hasAnnotation(
List<String> annotationNames)
boolean Returns whether or not this method is annotated with one of the provided annotation names. Annotation names can include simple and canonical names..
hasAnnotation(
String... annotationNames)
boolean Returns whether or not this method is annotated with one of the provided annotation names. Annotation names can include simple and canonical names..
hasAnnotationWithPrefix(
List<String> prefixes)
boolean Returns whether or not this method has an annotation that starts with one of the provided prefixes.
hasAnnotationWithPrefix(
String... prefixes)
boolean Returns whether or not this method has an annotation that starts with one of the provided prefixes.
inferredNullable boolean True if Squaretest has inferred this method can return null.
javadocExceptions FluentList<Exception> The list of exceptions declared in the method's Javadoc tags. This may include exceptions declared in the super methods' Javadoc tags.
jaxbListGetter boolean True if the method is likely a getter method generate by JAXB that returns a list. Such getter methods do not have corresponding setters. Developers modify the list by adding items to the returned list.
name String The name of the method
native boolean True if the method is native.
overloadSuffix String The suffix to append to the test method name to avoid method-name conflicts in the test class.
packageLocal boolean True if the method is package-local; false otherwise.
parameters FluentList<Variable> The method’s parameters
private boolean True if the method is private; false otherwise.
protected boolean True if the method is protected; false otherwise.
public boolean True if the method is public; false otherwise.
returnType Type The return type of the method or null if the method has none.
returnTypeCanBeAbsent boolean True if Squaretest has inferred this method can return either null or an "absent" value; e.g. Optional.empty().
shouldUseSimpleTest boolean Whether or not the template should render a simple, 1-line test method for this source method.
simpleGetter boolean True if the method is a getter.
simpleGetterOrSetter boolean True if the method is a getter or a setter.
simpleSetter boolean True if the method is a setter.
static boolean True if the method is static.
superMethods FluentList<Method> Contains all super methods this method overrides.
throwsCheckedException boolean True if the method throws a checked exception.
throwsException boolean True if the method throws an exception.
DependencyInteraction
Property Name Type Description
field ClassMember The ClassMember on which this DependencyInteraction's method is called.
method Method The Method called on the field in this DependencyInteraction.
methodCallExpression MethodCallExpression Contains information about the method call; e.g. the actual types of the arguments passed to the method if they can be determined.
MethodCallExpression
Property Name Type Description
arguments FluentList<ArgumentExpression> The arguments used in the method call.
type Type The type the method call expression evaluates to or null if the method has no return type. This type contains actual types for any type parameters inferred by the method call or class on which the method was called.
ArgumentExpression
Property Name Type Description
actualType Type The actual type of the argument. For arguments of type: T or Class<T>, Squaretest will attempt to provide the actual type used in the method call.
declaredType Type The declared type of the argument. This is the same as the type in the corresponding Method.
Constructor
Constructor is the same as Method, but implements Comparable<Constructor> such that it is ordered by number of parameters.
Variable
Property Name Type Description
annotations FluentList<Annotation> Contains the annotations on the Variable.
declaredName String The declared name for the variable; for ClassMembers this property contains the name of the member this it was created from; for method parameters, this contains the name of the parameter.
declaredNameWithoutPrefix String The declaredName with any prefixes removed; for method parameters, this is just the declaredName; for ClassMembers, this is the name with any recognized leading prefix (_, __, m, my, our) removed.
defaultInitExpression String Alias for type.defaultInitExpression.
final boolean True if the variable is declared to be final.
hasAnnotation(
List<String> annotationNames)
boolean Returns whether or not this Variable is annotated with one of the provided annotation names. Annotation names can include simple and canonical names..
hasAnnotation(
String... annotationNames)
boolean Returns whether or not this Variable is annotated with one of the provided annotation names. Annotation names can include simple and canonical names..
hasAnnotationWithPrefix(
List<String> prefixes)
boolean Returns whether or not this Variable has an annotation that starts with one of the provided prefixes.
hasAnnotationWithPrefix(
String... prefixes)
boolean Returns whether or not this Variable has an annotation that starts with one of the provided prefixes.
initExpression String Alias for type.initExpression.
shouldBeMocked boolean Alias for type.shouldBeMocked.
shouldStoreInReference boolean Set to true by default; this may be modified by logic in the template code based on the Quick Settings.
testClassLocalFieldName String For method parameters, this is the same as the declared name. For ClassMembers, this is determined based on the declared name and the IDE code style settings; this may be modified by logic in the template code based on the Quick Settings.
testClassMemberName String For ClassMembers, this is the same as the declaredName; for method parameters, this is determined based on the declared name and the IDE code style settings; this may be modified by logic in the template code based on the Quick Settings.
type Type The Type of the variable.
ClassMember
Name Type Description
Everything in Variable N/A N/A
accessLevel String Returns a String representing the access level for this member. Possible values are private, protected, packagePrivate, public.
final boolean True if the member is final.
packageLocal boolean True if the member field is package-local
possibleSourceVariables FluentList<Variable> List of references to Variables that could have provided the value for this ClassMember. This list includes pointers to constructor parameter(s) this field is assigned to. The ClassMember itself is also included in the list.
private boolean True if the member field is private
protected boolean True if the member field is protected
public boolean True if the member field is public
static boolean True if the member is static.
transient boolean True if the member is declared to be transient.
Exception
Name Type Description
checked boolean True if this is a checked exception.
type Type The type for this exception.
Type
Name Type Description
absentInitExpression String Represents an absent value for this type; e.g. Optional.empty(). This is usually "null".
allNames FluentList<String> Contains this type's canonical name as well as the canonical names of all super types of the type.
allNestedTypeParamsOverrideEquals boolean All type parameters override Object.equals() or are Class<T>, and all type parameters have allNestedTypeParamsOverrideEquals set to true.
allSuperTypeNames FluentList<String> Contains the canonical names of all super types of the type.
array boolean True if the type is an array; false otherwise.
brokenIoInitExpression String Represents a broken I/O value for this type; e.g. new BrokenInputStream(), or null if there isn't one.
canonicalName String Contains the canonical name of the type or null if the type has no canonical name, or the canonical name could not be determined.
canonicalNameOrName String Contains the canonical name if it is non-null. Otherwise, this contains the name of the type.
canonicalText String Contains the canonical text of the type.
classT boolean True if the type is Class<T>; false otherwise.
closeable boolean True if the type implements AutoCloseable.
createInitExpressionWith
  LocalFieldBeans(
  List<Type> types)
String Computes and returns an initExpression that uses the testClassLocalFieldNames of the provided types instead of their initExpressions.
deepArrayComponentType Type Contains the innermost component type for the array, if this type is an array. Otherwise, this contains null.
defaultInitExpression String The default expression used to obtain an instance of the class or “null” for types that are not Common Types.
dtoBean boolean True if the type is a DTO Bean.
dtoBeanWithInputIoProperty boolean True if the type is a data transfer object (DTO) bean that contains an Input I/O property; e.g. S3Object in the AWS SDK V1 API.
emptyInitExpression String Represents an empty value for this type; e.g. Collections.emptyList(), or null if there isn't one.
emptyIoInitExpression String Represents an empty I/O value for this type; e.g. InputStream.nullInputStream(), or null if there isn't one.
enum boolean True if the type is an enum.
failureInitExpression String Represents a failure value for this type; e.g. CompletableFuture.failedFuture(new Exception("message")), or null if there isn't one.
generic boolean True if the type is generic.
initExpression String Mutable field set to defaultInitExpression by default. This may be modified by the template code; see the Quick Settings initExpressionOverrides for details.
initExpressionBeans FluentList<Type> List of DTO beans used in the defaultInitExpression.
is(String
  canonicalName)
boolean Returns true if this type is an instance of the provided canonical name.
isAll(List<String>
  canonicalNames)
boolean Returns true if this type is an instance of all of the provided canonical names.
isAll(String...
  canonicalNames)
boolean Returns true if this type is an instance of all of the provided canonical names.
isAny(List<String>
  canonicalNames)
boolean Returns true if this type is an instance of one of the provided canonical names.
isAny(String...
  canonicalNames)
boolean Returns true if this type is an instance of one of the provided canonical names.
isOrHasAnyNestedTypeParamWith(
  List<String>
  canonicalNames)
boolean Returns true if this type is an instance of one of the provided canonical names or has a type parameter that is an instance of one of the provided canonical names.
isOrHasAnyNestedTypeParamWith(
  String... canonicalNames)
boolean Returns true if this type is an instance of one of the provided canonical names or has a type parameter that is an instance of one of the provided canonical names.
mockable boolean True if the type is mockable (non-final, non-static and not an enum)
nested boolean True if the type is nested inside a class.
optional boolean True if the type is optional.
overridesEquals boolean True if the type overrides Object.equals(...); false otherwise.
packageLocal boolean True if the type is package-local; false otherwise.
parameters FluentList<Type> Contains the list of type parameters for this type.
primitive boolean True if the type is primitive; false otherwise.
private boolean True if the type is private; false otherwise.
protected boolean True if the type is protected; false otherwise.
public boolean True if the type is public; false otherwise.
shouldBeMocked boolean Mutable field set to false for types with defaultInitExpressions != "null"; In all other cases, this is set to mockable; this may be modified by logic in the template code based on the Quick Settings.
shouldBeSpied boolean Mutable field indicating whether or not this type should be spied; i.e. Mockito.spy(..).
shouldStoreInReference boolean A boolean indicating whether or not the value of the initExpression should be stored in a reference (local variable or test class member) or used inline when needed.
simple boolean True if the type is simple. A simple type is one whose value should be used inline rather than stored in a local variable. Examples are: primitive types, enums, certain immutable types from the java.time package, etc.
springSimple boolean True if Spring components consider this type to be a simple value type; see BeanUtils.isSimpleValueType(Class<?>).
static boolean True if the type is a static class.
testClassLocalFieldName String Mutable property containing the name to use when storing an instance of this type in a local variable.
testClassMemberName String Mutable property containing the name to use when storing an instance of this type in a test class member.
type Type A convenience property that returns this type.
wildcard boolean True if the type is a wildcard; e.g. "? extends Foo".
AltInfo
Name Type Description
diExceptionToThrow Exception Mutable property containing the Exception the DependencyInteraction diThatThrows should throw in this test case.
diThatThrows DependencyInteraction Mutable property containing the DependencyInteraction that should throw an exception in this test case.
diToReturnAbsent DependencyInteraction Mutable property containing the DependencyInteraction that should return either null or an absent value in this test case.
diToReturnBrokenIo DependencyInteraction Mutable property containing the DependencyInteraction that should return a broken I/O value in this test case.
diToReturnEmpty DependencyInteraction Mutable property containing the DependencyInteraction that should return an empty value in this test case.
diToReturnEmptyIo DependencyInteraction Mutable property containing the DependencyInteraction that should return an empty I/O value in this test case.
diToReturnFailure DependencyInteraction Mutable property containing the DependencyInteraction that should return a failure value in this test case.
expectedException Exception Mutable property containing the Exception the alt flow test case should throw.
get(object) Object Retrieves extra information with the provided key that was stored for this test case. This can be retrieved with the Velocity map syntax; e.g. $altInfo['Key'].
paramWithBrokenIo Variable Mutable property containing the source method parameter that should return a broken I/O value in this test case.
paramWithEmptyIo Variable Mutable property containing the source method parameter that should return an empty I/O value in this test case.
put(object, object) void Stores the given (key, value) pair as extra information for this test case. This allows callers to add information needed to create their own alternate flow tests; e.g. #set($altInfo['Key1'] = 'Value1').
Annotation
Name Type Description
canonicalName String Contains the canonical name of the annotation or null if the canonical name could not be determined.
canonicalNameOrName String Contains the canonical name if it is non-null. Otherwise, this contains the name of the annotation.
name String Contains the name of the annotation.
parameters FluentList<AnnotationParameter> Contains the list of parameters passed to this annotation.
AnnotationParameter
Name Type Description
key String Contains the key of this annotation (key, value) pair.
value AnnotationValue Contains the value of this annotation (key, value) pair.
AnnotationValue
Name Type Description
text String Contains the text of the annotation value.
FluentList<T>
Method Return Type Description
Everything in List<T> N/A N/A
first T Returns the first item in the list or null if the list is empty.
second T Returns the second item in the list or null if the list contains fewer than two items.
third T Returns the third item in the list or null if the list contains fewer than three items.
fourth T Returns the fourth item in the list or null if the list contains fewer than four items.
fifth T Returns the fifth item in the list or null if the list contains fewer than five items.
concat(
  Collection<T> listToAppend)
FluentList<T> Returns a new list containing the items from this list followed by the items from listToAppend.
containsAnyWith(
  String attrNameExp,
  Object... searchValues)
boolean Returns whether or not the list contains an item with property: attrNameExp and a value in the searchValues.
containsAnyWithAnnotation(
  List<String> annotations)
boolean Returns whether or not the list contains any items with at least one of the provided annotations.
containsAnyWithAnnotation(
  String... annotations)
boolean Returns whether or not the list contains any items with at least one of the provided annotations.
containsAnyWithAnnotationPrefix(
  List<String> annotations)
boolean Returns whether or not the list contains any items with at least one annotation that starts with one of the given prefixes.
containsAnyWithAnnotationPrefix(
  String... prefixes)
boolean Returns whether or not the list contains any items with at least one annotation that starts with one of the given prefixes.
containsAnyWithNonNull(
  String attrNameExp)
boolean Returns whether or not the list contains an item with property: attrNameExp and a value that is not null.
containsAnyWithPrefix(
  String attrNameExp,
  List<String>)
boolean Returns whether or not the list contains an item with property: attrNameExp and a value that starts with one of the provided prefixes.
containsAnyWithPrefix(
  String attrNameExp,
  String... prefixes)
boolean Returns whether or not the list contains an item with property: attrNameExp and a value that starts with one of the provided prefixes.
containsAnyWithRegex(
  String attrNameExp,
  String regex)
boolean Returns whether or not the list contains an item with property: attrNameExp and a value that matches regular expression.
filter(
  String attrNameExp,
  Object... searchValues)
FluentList<T> Returns the list of items with property: attrNameExp and a value in searchValues.
filter(
  String attrNameExp)
FluentList<T> Returns the list of items with property: attrNameExp and value: true. This is equivalent to "filter(attrNameExp, true)".
filterItemsWithAnnotation(
  List<String> annotations)
FluentList<T> Returns a list containing all items with at least one of the provided annotations. The annotations parameter may contain simple names or canonical names.
filterItemsWithAnnotation(
  String... annotations)
FluentList<T> Returns a list containing all items with at least one of the provided annotations. The annotations parameter may contain simple names or canonical names.
filterItemsWithAnnotationPrefix(
  List<String> annotations)
FluentList<T> Returns a list containing all items with at least one annotation that starts with one of the given prefixes.
filterItemsWithAnnotationPrefix(
  String... prefixes)
FluentList<T> Returns a list containing all items with at least one annotation that starts with one of the given prefixes.
filterItemsWithAny(
  String attrNameExp,
  List<Object> attrValues)
FluentList<T> This returns a new list containing items in the list that have a property with name: attrNameExp and a value in attrValues.
filterItemsWithPrefix(
  String attrNameExp,
  List<String> prefixes)
FluentList<T> Returns the list of items with property: attrNameExp and a value that starts with one of the provided prefixes.
filterItemsWithPrefix(
  String attrNameExp,
  String... prefixes)
FluentList<T> Returns the list of items with property: attrNameExp and a value that starts with one of the provided prefixes.
filterItemsWithRegex(
  String attrNameExp,
  String regex)
FluentList<T> Returns the list of items with property: attrNameExp and a value that matches the provided regular expression.
filterItemsWithSameSourceVar(
  DependencyInteraction di)
FluentList<DI> Returns a FluentList containing DependencyInteractions whose field.possibleSourceVariables contain no elements in common with the provided dependencyInteraction.field.possibleSourceVariables.
filterOut(
  String attrNameExp,
  Object... searchValues)
FluentList<T> Returns a list excluding items with property: attrNameExp and a value in searchValues.
filterOut(
  String attrNameExp)
FluentList<T> Returns a list excluding items with property: attrNameExp and a value of true.
filterOut(String attrNameExp) FluentList<T> Returns a list excluding items with property: attrNameExp and a value of true. This is equivalent to "filterOut(attrNameExp, true)"
filterOutItem(
  T itemToRemove)
FluentList<T> Returns a list excluding all items equal to itemToRemove.
filterOutItemsWithAnnotation(
  List<String> annotations)
FluentList<T> Returns a list containing all items that do not have at least one of the provided annotations. The annotations parameter may contain simple names or canonical names.
filterOutItemsWithAnnotation(
  String... annotations)
FluentList<T> Returns a list containing all items that do not have at least one of the provided annotations. The annotations parameter may contain simple names or canonical names.
filterOutItemsWithAnnotationPrefix(
  List<String> annotations)
FluentList<T> Returns a list containing all items that do not have at least one annotation that starts with one of the given prefixes.
filterOutItemsWithAnnotationPrefix(
  String... prefixes)
FluentList<T> Returns a list containing all items that do not have at least one annotation that starts with one of the given prefixes.
filterOutItemsWithPrefix(
  String attrNameExp,
  List<String> prefixes)
FluentList<T> Returns a list excluding items with property: attrNameExp and a value that starts with one of the provided prefixes.
filterOutItemsWithPrefix(
  String attrNameExp,
  String... prefixes)
FluentList<T> Returns a list excluding items with property: attrNameExp and a value that starts with one of the provided prefixes.
filterOutItemsWithRegex(
  String attrNameExp,
  String regex)
FluentList<T> Returns a list excluding items with property: attrNameExp and a value that matches the provided regular expression.
filterOutItemsWithSameSourceVar(
  DependencyInteraction di)
FluentList<DI> Returns a FluentList containing DependencyInteractions whose field.possibleSourceVariables contain at least one element in common with the provided dependencyInteraction.field.possibleSourceVariables.
flatMap(String attrNameExp)
FluentList<?> Invokes the given attrNameExp on each item in the list and returns a new list containing all values returned from the invocations. If an invocation returns a List, all items in the list are added to the return list; i.e. the lists are flattened.
getOrNull(
  int index)
T Returns the item in the list at the specified index or null if the index is out of bounds for the list.
indexOfAny(
  String attrNameExp,
  Object... searchValues)
int Returns the index of the first item in the list contains property: attrNameExp and a value in searchValues; this returns -1 if no such item is in the list.
intersection(
  Iterable iter)
FluentList<T> Returns the intersection of this list and the provided Iterable.
itemsAfter(obj) FluentList<T> Returns a list containing items after obj or an empty list of obj is not present in the list.
itemsBefore(obj) FluentList<T> Returns a list containing items before obj or an empty list of obj is not present in the list.
map(String attrNameExp)
FluentList<?> Returns a list containing the results of invoking the given attributeNameExpression on each element of this list.
satisfiedBy(
  List<? extends Api.Variable>
  dependencies)
  
FluentList<DI> Returns the list of dependency interactions satisfied by the provided dependencies. More formally, a DependencyInteraction di is included in the list if di.field.possibleSourceVariables.intersection(dependencies) is not empty.
union(
  Iterable iter,
  String attrNameExp)
FluentList<T> Returns the union of this list and the provided Iterable using the attribute value retrieved by attrNameExp to determine equality.
union(
  Iterable iter)
FluentList<T> Returns the union of this list and the provided Iterable.
CodeStyleUtils
Method Return Type Description
beginMethodScope()
void
Informs CodeStyleUtils this is the start of a Java or Groovy method. Invoking this method enables CodeStyleUtils to suggest local variable names that do not conflict others declared in the same method.
endMethodScope()
void
Informs CodeStyleUtils this is the end of a Java or Groovy method. Invoking this method enables CodeStyleUtils to suggest local variable names that do not conflict others declared in the same method.
suggestLocalFieldName(
  String className)
String
Returns the suggested name to use for a local field of type className based on the IDE code style settings.
suggestMemberName(
  String className)
String
Returns the suggested name to use for a member of type className based on the IDE code style settings.
updateLocalFieldNameWithMethodScope(
  Type type)
void
Updates the testClassLocalFieldName property of the provided type in a way that avoids name collisions with other variables or types that were updated after CodeStyleUtils.beginMethodScope() was invoked.
updateLocalFieldNameWithMethodScope(
  Variable variable)
void
Updates the testClassLocalFieldName property of the provided variable in a way that avoids name collisions with other variables or types that were updated after CodeStyleUtils.beginMethodScope() was invoked.
ClassUtils
Method Return Type Description
isInTestClasspath(
  String canonicalName)
boolean
Returns whether or not a class with the given canonical name is in the classpath of the sources root in which the test class will be created.
removePackageQualifiers(
  String canonicalText)
boolean
Attempts to remove the package qualifiers from the provided canonical text and returns the result.
resolveClass(
  Type type)
SourceClass Returns a SourceClass object for the provided type or null if one could not be found. Note: the Method.dependencyInteraction properties will not be populated in the returned SourceClass.
resolveClass(
  Variable var)
SourceClass Returns a SourceClass object for the provided Variable or null if one could not be found. Note: the Method.dependencyInteraction properties will not be populated in the returned SourceClass.
resolveClass(
  String canonicalName)
SourceClass Returns a SourceClass object for the provided canonical name or null if one could not be found. Note: the Method.dependencyInteraction properties will not be populated in the returned SourceClass.
UiUtils
Method Return Type Description
askUserToConfirmSettings(
  Map<String, Object> settings)
Map<String, Object> Shows a dialog asking the user to confirm the provided settings. Currently, Squaretest only asks the user to confirm which dependencies should be mocked.
FluentList
Method Return Type Description
emptyList()
FluentList<T> Returns an empty FluentList<T>.
of(T... items)
FluentList<T> Returns a mutable FluentList<T> containing the provided items.
MutableBoolean
Method Return Type Description
create(boolean value)
MutableBoolean Returns a MutableBoolean with the specified value.
MutableInt
Method Return Type Description
create(int value)
MutableInt Returns a MutableInt with the specified value.
MutableObject
Method Return Type Description
create()
MutableObject Returns a MutableObject with the value set to null.
create(Object value)
MutableObject Returns a MutableObject with the specified value.
MutableString
Method Return Type Description
create()
MutableString Returns a MutableObject<String> with the value set to null.
create(String value)
MutableString Returns a MutableObject<String> with the specified value.
AltInfoFactory
Method Return Type Description
fromDiThatThrows(di,
  diExceptionToThrow,
  expectedException)
AltInfo Returns an AltInfo object with the provided DependencyInteraction that should throw, the exceptionToThrow and expectedException in the test case.
fromDiThatThrows(di,
  diExceptionToThrow)
AltInfo Returns an AltInfo object with the provided DependencyInteraction that should throw the provided Exception in the test case.
fromDiThatThrows(di)
AltInfo Returns an AltInfo object with the provided DependencyInteraction that should throw an exception in the test case.
fromDiToReturnAbsent(di)
AltInfo Returns an AltInfo object with the provided DependencyInteraction that should return null or an absent value for the test case.
fromDiToReturnBrokenIo(di,
  expectedException)
AltInfo Returns an AltInfo object with the provided DependencyInteraction that should return a broken I/O value and expected exception for the test case.
fromDiToReturnBrokenIo(di)
AltInfo Returns an AltInfo object with the provided DependencyInteraction that should return a broken I/O value for the test case.
fromDiToReturnEmpty(di)
AltInfo Returns an AltInfo object with the provided DependencyInteraction that should return an empty value for the test case.
fromDiToReturnEmptyIo(di)
AltInfo Returns an AltInfo object with the provided DependencyInteraction that should return an empty I/O value for the test case.
fromDiToReturnFailure(di,
  expectedException)
AltInfo Returns an AltInfo object with the provided DependencyInteraction that should return a failure value and expectedException for the test case.
fromDiToReturnFailure(di)
AltInfo Returns an AltInfo object with the provided DependencyInteraction that should return a failure value for the test case.
fromExpectedException(
  expectedException)
AltInfo Returns an AltInfo object with the provided expectedException.
fromKeyValuePair(key, value)
AltInfo Returns an AltInfo object with the provided (key, value) pair. See AltInfo.put(key, value).
fromParamWithBrokenIo(
  param, expectedException)
AltInfo Returns an AltInfo object with the provided Variable that should contain a broken I/O value and expectedException for the test case.
fromParamWithBrokenIo(
  param)
AltInfo Returns an AltInfo object with the provided Variable that should contain a broken I/O value for the test case.
fromParamWithEmptyIo(
  param)
AltInfo Returns an AltInfo object with the provided Variable that should contain an empty I/O value in the test case.
newValue()
AltInfo Returns an empty AltInfo object. This represents the primary flow test case.
ListUtils
Method Return Type Description
nullToEmpty(List<?> theList)
FluentList<?>
Returns theList if it is non-null and an empty FluentList otherwise.
StringUtils
Method Return Type Description
Everything in StringUtils N/A Everything in org.apache.commons.lang3.StringUtils.
longest(
  String... strings)
String Returns the longest String provided.
longest(
  List<String> strings)
String Returns the longest String provided.
shortest(
  String... strings)
String Returns the shortest String provided.
shortest(
  List<String> strings)
String Returns the shortest String provided.
substringsBetween(
  String str,
  String tag)
String[] Searches a String for substrings delimited by the provided tag, and returns all matching substrings in an array.
Method Comment Hints

Previous version of Squaretest included Velocity templates with special comments of the form: "#* sq_hint:setup_comment *#". These are no longer used.

Newlines

Squaretest removes all but one trailing newline at the end of the generated unit test file. This allows developers to have space between macros and comments without concern that they will appear in the unit tests.

Squaretest also replaces each group of 3 or more newlines in the generated unit test file with 2 newlines. This removes the need for developers to add extra branching logic to templates to ensure the unit test contains an appropriate number of newlines between sections.

Code Cleanup

Squaretest performs several, automated code-cleanup tasks on the generated test class. These include the following.

  • Optimize imports according to the IDE code style settings.
  • Shorten class references (replace fully qualified names with imports)
    • This allows you to use fully qualified names throughout the template without having them appear in the generated test class.
  • Reformat all code in the test class according to the IDE code style settings.
    • This allows you to indent the template code in a way that is easy-to-read, without having to worry about the generated Java code being over-indented.
  • Remove unnecessary semicolons.
    • This allows the Groovy templates to use semicolons to mark the ends of statements.
  • Remove unnecessary throws clauses.
    • This allows templates to include "throws Exception" on all generated methods instead of needing to determine whether the clause is necessary in each method.

Examples

The following examples show source classes along with their corresponding test classes that were generated by Squaretest. In many cases, the user only needs to fill in the placeholder values, and update the assertions to complete the tests.
Standard Component
The source class is a standard Java component that retrieves deals from a web service, converts them into display versions and returns them. The test class generated by Squaretest contains tests for the following cases.
  • The primary flow where the deals service returns a list containing one item.
  • The alternate flow where the deals service returns an error.
  • The alternate flow where the connection to the deals service was interrupted.
                
package com.squaretest.demo1;

import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class DealsServiceAdapter {

    private static final Logger Log = Logger.getLogger(DealsServiceAdapter.class.getName());

    private final DealsServiceClient dealsService;

    public DealsServiceAdapter(final DealsServiceClient dealsService) {
        this.dealsService = dealsService;
    }

    public List<DisplayDeal> safeGetDeals(final String userId) {
        try {
            final GetDealsRequest request = new GetDealsRequest();
            request.setUserId(userId);
            return convertToDisplayDeals(dealsService.getDeals(request).getActiveDeals());
        } catch (final ServiceException | NetworkException e) {
            Log.log(Level.WARNING, "Exception querying deals service.", e);
            return Collections.emptyList();
        }
    }

    private List<DisplayDeal> convertToDisplayDeals(final List<Deal> deals) {
        // Omitted: code to convert deals into display deals.
        return Collections.emptyList();
    }
}
                
              
Source Class
>
              
package com.squaretest.demo1;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.math.BigDecimal;
import java.net.URI;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class DealsServiceAdapterTest {

    @Mock
    private DealsServiceClient mockDealsService;

    private DealsServiceAdapter dealsServiceAdapterUnderTest;

    @BeforeEach
    void setUp() {
        dealsServiceAdapterUnderTest = new DealsServiceAdapter(mockDealsService);
    }

    @Test
    void testSafeGetDeals() throws Exception {
        // Setup
        final List<DisplayDeal> expectedResult = List.of(
                new DisplayDeal("id", "productName", new BigDecimal("0.00"), new URI("http://example.com/")));

        // Configure DealsServiceClient.getDeals(...).
        final DealsServiceResponse dealsServiceResponse = new DealsServiceResponse();
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        dealsServiceResponse.setActiveDeals(List.of(deal));
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenReturn(dealsServiceResponse);

        // Run the test
        final List<DisplayDeal> result = dealsServiceAdapterUnderTest.safeGetDeals("userId");

        // Verify the results
        assertEquals(expectedResult, result);
    }

    @Test
    void testSafeGetDeals_DealsServiceClientThrowsServiceException() throws Exception {
        // Setup
        final List<DisplayDeal> expectedResult = List.of(
                new DisplayDeal("id", "productName", new BigDecimal("0.00"), new URI("http://example.com/")));
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenThrow(ServiceException.class);

        // Run the test
        final List<DisplayDeal> result = dealsServiceAdapterUnderTest.safeGetDeals("userId");

        // Verify the results
        assertEquals(expectedResult, result);
    }

    @Test
    void testSafeGetDeals_DealsServiceClientThrowsNetworkException() throws Exception {
        // Setup
        final List<DisplayDeal> expectedResult = List.of(
                new DisplayDeal("id", "productName", new BigDecimal("0.00"), new URI("http://example.com/")));
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenThrow(NetworkException.class);

        // Run the test
        final List<DisplayDeal> result = dealsServiceAdapterUnderTest.safeGetDeals("userId");

        // Verify the results
        assertEquals(expectedResult, result);
    }
}
              
            
Generated Test Class
<
Standard Component with JAXB
The source class is the same as the Standard Component but with a DealsServiceResponse class generated by JAXB. Deals are added to the response by invoking response.getActiveDeals().add(..). The generated test class contains tests for the following cases.
  • The primary flow where the deals service returns a list containing one item.
  • The alternate flow where the deals service returns an error.
  • The alternate flow where the connection to the deals service was interrupted.
                
package com.squaretest.demo20;

import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class DealsServiceAdapter {

    private static final Logger Log = Logger.getLogger(DealsServiceAdapter.class.getName());

    private final DealsServiceClient dealsService;

    public DealsServiceAdapter(final DealsServiceClient dealsService) {
        this.dealsService = dealsService;
    }

    public List<DisplayDeal> safeGetDeals(final String userId) {
        try {
            final GetDealsRequest request = new GetDealsRequest();
            request.setUserId(userId);
            return convertToDisplayDeals(dealsService.getDeals(request).getActiveDeals());
        } catch (final ServiceException | NetworkException e) {
            Log.log(Level.WARNING, "Exception querying deals service.", e);
            return Collections.emptyList();
        }
    }

    private List<DisplayDeal> convertToDisplayDeals(final List<Deal> deals) {
        // Omitted: code to convert deals into display deals.
        return Collections.emptyList();
    }
}
                
              
Source Class
>
              
package com.squaretest.demo20;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.math.BigDecimal;
import java.net.URI;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class DealsServiceAdapterTest {

    @Mock
    private DealsServiceClient mockDealsService;

    private DealsServiceAdapter dealsServiceAdapterUnderTest;

    @BeforeEach
    void setUp() {
        dealsServiceAdapterUnderTest = new DealsServiceAdapter(mockDealsService);
    }

    @Test
    void testSafeGetDeals() throws Exception {
        // Setup
        final List<DisplayDeal> expectedResult = List.of(new DisplayDeal("id", "productName", new BigDecimal("0.00"), new URI("http://example.com/")));

        // Configure DealsServiceClient.getDeals(...).
        final DealsServiceResponse dealsServiceResponse = new DealsServiceResponse();
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        dealsServiceResponse.getActiveDeals().addAll(List.of(deal));
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenReturn(dealsServiceResponse);

        // Run the test
        final List<DisplayDeal> result = dealsServiceAdapterUnderTest.safeGetDeals("userId");

        // Verify the results
        assertEquals(expectedResult, result);
    }

    @Test
    void testSafeGetDeals_DealsServiceClientThrowsServiceException() throws Exception {
        // Setup
        final List<DisplayDeal> expectedResult = List.of(new DisplayDeal("id", "productName", new BigDecimal("0.00"), new URI("http://example.com/")));
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenThrow(ServiceException.class);

        // Run the test
        final List<DisplayDeal> result = dealsServiceAdapterUnderTest.safeGetDeals("userId");

        // Verify the results
        assertEquals(expectedResult, result);
    }

    @Test
    void testSafeGetDeals_DealsServiceClientThrowsNetworkException() throws Exception {
        // Setup
        final List<DisplayDeal> expectedResult = List.of(new DisplayDeal("id", "productName", new BigDecimal("0.00"), new URI("http://example.com/")));
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenThrow(NetworkException.class);

        // Run the test
        final List<DisplayDeal> result = dealsServiceAdapterUnderTest.safeGetDeals("userId");

        // Verify the results
        assertEquals(expectedResult, result);
    }
}
              
            
Generated Test Class
<
Asynchronous Component
The source class is an asynchronous Java component that performs the same task as the Standard Component but in a background thread. The class returns a CompletableFuture that callers can use to manage the background task. The test class contains tests for the following cases.
  • The primary flow where the deals service returns a list containing one item.
  • The alternate flow where the deals service returns an error.
  • The alternate flow where the connection to the deals service was interrupted.
The test methods contain doAnswer(..) statements to invoke the Runnable passed to the ExecutorService's execute(..) method. The execute(..) method is called by CompletableFuture.supplyAsync(..).
                
package com.squaretest.demo8;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;
import java.util.logging.Logger;

public class DealsServiceAdapterAsync {

    private static final Logger Log = Logger.getLogger(DealsServiceAdapterAsync.class.getName());

    private final DealsServiceClient dealsService;
    private final ExecutorService executorService;

    public DealsServiceAdapterAsync(
            final DealsServiceClient dealsService, final ExecutorService executorService) {
        this.dealsService = dealsService;
        this.executorService = executorService;
    }

    public CompletableFuture<List<DisplayDeal>> getDeals(final String userId) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return getDealsInternal(userId);
            } catch (final ServiceException | NetworkException e) {
                Log.log(Level.WARNING, "Exception querying deals service.", e);
                throw new CompletionException(e);
            }
        }, executorService);
    }

    private List<DisplayDeal> getDealsInternal(final String userId) throws ServiceException, NetworkException {
        final GetDealsRequest request = new GetDealsRequest();
        request.setUserId(userId);
        return convertToDisplayDeals(dealsService.getDeals(request).getActiveDeals());
    }

    private List<DisplayDeal> convertToDisplayDeals(final List<Deal> deals) {
        // Omitted: code to convert deals into display deals.
        return Collections.emptyList();
    }
}
                
              
Source Class
>
              
package com.squaretest.demo8;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class DealsServiceAdapterAsyncTest {

    @Mock
    private DealsServiceClient mockDealsService;
    @Mock
    private ExecutorService mockExecutorService;

    private DealsServiceAdapterAsync dealsServiceAdapterAsyncUnderTest;

    @BeforeEach
    void setUp() {
        dealsServiceAdapterAsyncUnderTest = new DealsServiceAdapterAsync(
                mockDealsService, mockExecutorService);
    }

    @Test
    void testGetDeals() throws Exception {
        // Setup
        doAnswer(invocation -> {
            ((Runnable) invocation.getArguments()[0]).run();
            return null;
        }).when(mockExecutorService).execute(any(Runnable.class));

        // Configure DealsServiceClient.getDeals(...).
        final DealsServiceResponse dealsServiceResponse = new DealsServiceResponse();
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        dealsServiceResponse.setActiveDeals(List.of(deal));
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenReturn(dealsServiceResponse);

        // Run the test
        final CompletableFuture<List<DisplayDeal>> result = dealsServiceAdapterAsyncUnderTest.getDeals("userId");

        // Verify the results
        verify(mockExecutorService).execute(any(Runnable.class));
    }

    @Test
    void testGetDeals_DealsServiceClientThrowsServiceException() throws Exception {
        // Setup
        doAnswer(invocation -> {
            ((Runnable) invocation.getArguments()[0]).run();
            return null;
        }).when(mockExecutorService).execute(any(Runnable.class));
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenThrow(ServiceException.class);

        // Run the test
        final CompletableFuture<List<DisplayDeal>> result = dealsServiceAdapterAsyncUnderTest.getDeals("userId");

        // Verify the results
        verify(mockExecutorService).execute(any(Runnable.class));
    }

    @Test
    void testGetDeals_DealsServiceClientThrowsNetworkException() throws Exception {
        // Setup
        doAnswer(invocation -> {
            ((Runnable) invocation.getArguments()[0]).run();
            return null;
        }).when(mockExecutorService).execute(any(Runnable.class));
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenThrow(NetworkException.class);

        // Run the test
        final CompletableFuture<List<DisplayDeal>> result = dealsServiceAdapterAsyncUnderTest.getDeals("userId");

        // Verify the results
        verify(mockExecutorService).execute(any(Runnable.class));
    }
}
              
            
Generated Test Class
<
Asynchronous Component with Guava
The source class is the same as the previous Asynchronous Component example. The test class is generated in an environment where Google Guava is available on the test classpath. The test class contains tests for the following cases.
  • The primary flow where the deals service returns a list containing one item.
  • The alternate flow where the deals service returns an error.
  • The alternate flow where the connection to the deals service was interrupted.
Squaretest constructs the source class using the direct executor service in Google Guava instead of a mock.
                
package com.squaretest.demo9;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;
import java.util.logging.Logger;

public class DealsServiceAdapterAsync {

    private static final Logger Log = Logger.getLogger(DealsServiceAdapterAsync.class.getName());

    private final DealsServiceClient dealsService;
    private final ExecutorService executorService;

    public DealsServiceAdapterAsync(
            final DealsServiceClient dealsService,
            final ExecutorService executorService) {
        this.dealsService = dealsService;
        this.executorService = executorService;
    }

    public CompletableFuture<List<DisplayDeal>> getDeals(final String userId) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return getDealsInternal(userId);
            } catch (final ServiceException | NetworkException e) {
                Log.log(Level.WARNING, "Exception querying deals service.", e);
                throw new CompletionException(e);
            }
        }, executorService);
    }

    private List<DisplayDeal> getDealsInternal(final String userId) throws ServiceException, NetworkException {
        final GetDealsRequest request = new GetDealsRequest();
        request.setUserId(userId);
        return convertToDisplayDeals(dealsService.getDeals(request).getActiveDeals());
    }

    private List<DisplayDeal> convertToDisplayDeals(final List<Deal> deals) {
        // Omitted: code to convert deals into display deals.
        return Collections.emptyList();
    }
}
                
              
Source Class
>
              
package com.squaretest.demo9;

import com.google.common.util.concurrent.MoreExecutors;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class DealsServiceAdapterAsyncTest {

    @Mock
    private DealsServiceClient mockDealsService;

    private DealsServiceAdapterAsync dealsServiceAdapterAsyncUnderTest;

    @BeforeEach
    void setUp() {
        dealsServiceAdapterAsyncUnderTest = new DealsServiceAdapterAsync(mockDealsService,
                MoreExecutors.newDirectExecutorService());
    }

    @Test
    void testGetDeals() throws Exception {
        // Setup

        // Configure DealsServiceClient.getDeals(...).
        final DealsServiceResponse dealsServiceResponse = new DealsServiceResponse();
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        dealsServiceResponse.setActiveDeals(List.of(deal));
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenReturn(dealsServiceResponse);

        // Run the test
        final CompletableFuture<List<DisplayDeal>> result = dealsServiceAdapterAsyncUnderTest.getDeals("userId");

        // Verify the results
    }

    @Test
    void testGetDeals_DealsServiceClientThrowsServiceException() throws Exception {
        // Setup
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenThrow(ServiceException.class);

        // Run the test
        final CompletableFuture<List<DisplayDeal>> result = dealsServiceAdapterAsyncUnderTest.getDeals("userId");

        // Verify the results
    }

    @Test
    void testGetDeals_DealsServiceClientThrowsNetworkException() throws Exception {
        // Setup
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenThrow(NetworkException.class);

        // Run the test
        final CompletableFuture<List<DisplayDeal>> result = dealsServiceAdapterAsyncUnderTest.getDeals("userId");

        // Verify the results
    }
}
              
            
Generated Test Class
<
AWS SDK V1 S3 Adapter
The source class is a component that retrieves purchase order PDF documents from an S3 bucket. The test class generated by Squaretest contains tests for the following cases.
  • The primary flow where the bucket contains the purchase order.
  • The alternate flow where the bucket contains a purchase order with no content (an empty object).
  • The alternate flow where the bucket contains a purchase order, but the connection is interrupted while it is being downloaded.
  • The alternate flow where the bucket does not contain the purchase order or S3 returns an error.
  • The alternate flow where S3 could not be reached due to a network error on the client side.
Squaretest also includes verify(..) statements to ensure the InputStream returned by the S3 client is closed.
                
package com.squaretest.demo3;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.S3Object;
import org.apache.commons.lang3.Validate;
import org.apache.pdfbox.pdmodel.PDDocument;

import java.io.IOException;

public class PurchaseOrderStore {

    private static final String PathFormat = "%s/purchaseOrder.pdf";

    private final AmazonS3 s3Client;
    private final MetricAdapter metricAdapter;
    private final String bucketName;

    public PurchaseOrderStore(
            final AmazonS3 s3Client,
            final MetricAdapter metricAdapter,
            final String bucketName) {
        this.s3Client = s3Client;
        this.metricAdapter = metricAdapter;
        this.bucketName = bucketName;
    }

    public PDDocument getPurchaseOrder(final String orderId) throws PurchaseOrderStoreException {
        Validate.notBlank(orderId, "Orderid cannot be blank");
        final String path = String.format(PathFormat, orderId);
        try (final S3Object s3Object = s3Client.getObject(bucketName, path)) {
            if(s3Object == null) {
                metricAdapter.recordEvent(MetricEvent.NoObjectFound);
                throw new PurchaseOrderStoreException(String.format("S3Object with path: %s not found", path));
            }
            final PDDocument purchaseOrderDoc = PDDocument.load(s3Object.getObjectContent());
            metricAdapter.recordEvent(MetricEvent.Success);
            return purchaseOrderDoc;
        } catch (final AmazonServiceException e) {
            metricAdapter.recordEvent(MetricEvent.S3Exception);
            throw new PurchaseOrderStoreException(
                    String.format("AmazonServiceException while downloading object with path: %s", path), e);
        } catch (final SdkClientException e) {
            metricAdapter.recordEvent(MetricEvent.SDKException);
            throw new PurchaseOrderStoreException(
                    String.format("SdkClientException while downloading object with path: %s", path), e);
        } catch (final IOException e) {
            metricAdapter.recordEvent(MetricEvent.IOException);
            throw new PurchaseOrderStoreException(
                    String.format("IOException while downloading object with path: %s", path), e);
        }
    }
}
                
              
Source Class
>
              
package com.squaretest.demo3;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.S3Object;
import org.apache.commons.io.input.BrokenInputStream;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class PurchaseOrderStoreTest {

    @Mock
    private AmazonS3 mockS3Client;
    @Mock
    private MetricAdapter mockMetricAdapter;

    private PurchaseOrderStore purchaseOrderStoreUnderTest;

    @BeforeEach
    void setUp() {
        purchaseOrderStoreUnderTest = new PurchaseOrderStore(mockS3Client, mockMetricAdapter, "bucketName");
    }

    @Test
    void testGetPurchaseOrder() throws Exception {
        // Setup

        // Configure AmazonS3.getObject(...).
        final S3Object spyS3Object = spy(new S3Object());
        spyS3Object.setBucketName("bucketName");
        spyS3Object.setKey("key");
        spyS3Object.setObjectContent(new ByteArrayInputStream("content".getBytes()));
        when(mockS3Client.getObject("bucketName", "key")).thenReturn(spyS3Object);

        // Run the test
        final PDDocument result = purchaseOrderStoreUnderTest.getPurchaseOrder("orderId");

        // Verify the results
        verify(spyS3Object).close();
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetPurchaseOrder_AmazonS3ReturnsNoContent() throws Exception {
        // Setup

        // Configure AmazonS3.getObject(...).
        final S3Object spyS3Object = spy(new S3Object());
        spyS3Object.setBucketName("bucketName");
        spyS3Object.setKey("key");
        spyS3Object.setObjectContent(InputStream.nullInputStream());
        when(mockS3Client.getObject("bucketName", "key")).thenReturn(spyS3Object);

        // Run the test
        final PDDocument result = purchaseOrderStoreUnderTest.getPurchaseOrder("orderId");

        // Verify the results
        verify(spyS3Object).close();
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetPurchaseOrder_AmazonS3ReturnsBrokenIo() throws Exception {
        // Setup

        // Configure AmazonS3.getObject(...).
        final S3Object spyS3Object = spy(new S3Object());
        spyS3Object.setBucketName("bucketName");
        spyS3Object.setKey("key");
        spyS3Object.setObjectContent(new BrokenInputStream());
        when(mockS3Client.getObject("bucketName", "key")).thenReturn(spyS3Object);

        // Run the test
        assertThrows(PurchaseOrderStoreException.class, () -> purchaseOrderStoreUnderTest.getPurchaseOrder("orderId"));
        verify(spyS3Object).close();
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetPurchaseOrder_AmazonS3ThrowsSdkClientException() throws Exception {
        // Setup
        when(mockS3Client.getObject("bucketName", "key")).thenThrow(SdkClientException.class);

        // Run the test
        final PDDocument result = purchaseOrderStoreUnderTest.getPurchaseOrder("orderId");

        // Verify the results
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetPurchaseOrder_AmazonS3ThrowsAmazonServiceException() throws Exception {
        // Setup
        when(mockS3Client.getObject("bucketName", "key")).thenThrow(AmazonServiceException.class);

        // Run the test
        final PDDocument result = purchaseOrderStoreUnderTest.getPurchaseOrder("orderId");

        // Verify the results
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }
}
              
            
Generated Test Class
<
AWS SDK V2 S3 Adapter
The source class is a component that retrieves purchase order PDF documents from an S3 bucket. The test class generated by Squaretest contains tests for the following cases.
  • The primary flow where the bucket contains the purchase order.
  • The alternate flow where the bucket contains a purchase order with no content (an empty object).
  • The alternate flow where the bucket contains a purchase order, but the connection is interrupted while it is being downloaded.
  • The alternate flow where the bucket does not contain the purchase order.
  • The alternate flow where S3 could not be reached due to a network error on the client side.
  • The alternate flow where S3 returns a service error.
Squaretest also includes verify(..) statements to ensure the InputStream returned by the S3 client is closed.
                
package com.squaretest.demo2;

import org.apache.commons.lang3.Validate;
import org.apache.pdfbox.pdmodel.PDDocument;
import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
import software.amazon.awssdk.services.s3.model.S3Exception;

import java.io.IOException;

public class PurchaseOrderStore {

    private static final String PathFormat = "%s/purchaseOrder.pdf";

    private final S3Client s3Client;
    private final MetricAdapter metricAdapter;
    private final String bucketName;

    public PurchaseOrderStore(
            final S3Client s3Client,
            final MetricAdapter metricAdapter,
            final String bucketName) {
        this.s3Client = s3Client;
        this.metricAdapter = metricAdapter;
        this.bucketName = bucketName;
    }

    public PDDocument getPurchaseOrder(final String orderId) throws PurchaseOrderStoreException {
        Validate.notBlank(orderId, "Orderid cannot be blank");
        final String path = String.format(PathFormat, orderId);
        try (final ResponseInputStream<GetObjectResponse> s3Object = s3Client.getObject(
                GetObjectRequest.builder().bucket(bucketName).key(path).build())) {
            final PDDocument purchaseOrderDoc = PDDocument.load(s3Object);
            metricAdapter.recordEvent(MetricEvent.Success);
            return purchaseOrderDoc;
        } catch (final NoSuchKeyException e) {
            metricAdapter.recordEvent(MetricEvent.NoObjectFound);
            throw new PurchaseOrderStoreException(String.format("S3Object with path: %s not found", path), e);
        } catch (final S3Exception e) {
            metricAdapter.recordEvent(MetricEvent.S3Exception);
            throw new PurchaseOrderStoreException(
                    String.format("S3Exception while downloading object with path: %s", path), e);
        } catch (final SdkClientException e) {
            metricAdapter.recordEvent(MetricEvent.SDKException);
            throw new PurchaseOrderStoreException(
                    String.format("SdkClientException while downloading object with path: %s", path), e);
        } catch (final IOException e) {
            metricAdapter.recordEvent(MetricEvent.IOException);
            throw new PurchaseOrderStoreException(
                    String.format("IOException while downloading object with path: %s", path), e);
        }
    }
}
                
              
Source Class
>
              
package com.squaretest.demo2;

import org.apache.commons.io.input.BrokenInputStream;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import software.amazon.awssdk.awscore.exception.AwsServiceException;
import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.http.AbortableInputStream;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
import software.amazon.awssdk.services.s3.model.S3Exception;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class PurchaseOrderStoreTest {

    @Mock
    private S3Client mockS3Client;
    @Mock
    private MetricAdapter mockMetricAdapter;

    private PurchaseOrderStore purchaseOrderStoreUnderTest;

    @BeforeEach
    void setUp() {
        purchaseOrderStoreUnderTest = new PurchaseOrderStore(mockS3Client, mockMetricAdapter, "bucketName");
    }

    @Test
    void testGetPurchaseOrder() throws Exception {
        // Setup

        // Configure S3Client.getObject(...).
        final ResponseInputStream<GetObjectResponse> spyResponseInputStream = spy(new ResponseInputStream<>(
                GetObjectResponse.builder().build(),
                AbortableInputStream.create(new ByteArrayInputStream("objectContent".getBytes()))));
        when(mockS3Client.getObject(GetObjectRequest.builder()
                .bucket("bucketName")
                .key("key")
                .build())).thenReturn(spyResponseInputStream);

        // Run the test
        final PDDocument result = purchaseOrderStoreUnderTest.getPurchaseOrder("orderId");

        // Verify the results
        verify(spyResponseInputStream).close();
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetPurchaseOrder_S3ClientReturnsNoContent() throws Exception {
        // Setup

        // Configure S3Client.getObject(...).
        final ResponseInputStream<GetObjectResponse> spyResponseInputStream = spy(new ResponseInputStream<>(
                GetObjectResponse.builder().build(), AbortableInputStream.create(InputStream.nullInputStream())));
        when(mockS3Client.getObject(GetObjectRequest.builder()
                .bucket("bucketName")
                .key("key")
                .build())).thenReturn(spyResponseInputStream);

        // Run the test
        final PDDocument result = purchaseOrderStoreUnderTest.getPurchaseOrder("orderId");

        // Verify the results
        verify(spyResponseInputStream).close();
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetPurchaseOrder_S3ClientReturnsBrokenIo() throws Exception {
        // Setup

        // Configure S3Client.getObject(...).
        final ResponseInputStream<GetObjectResponse> spyResponseInputStream = spy(new ResponseInputStream<>(
                GetObjectResponse.builder().build(), AbortableInputStream.create(new BrokenInputStream())));
        when(mockS3Client.getObject(GetObjectRequest.builder()
                .bucket("bucketName")
                .key("key")
                .build())).thenReturn(spyResponseInputStream);

        // Run the test
        assertThrows(PurchaseOrderStoreException.class, () -> purchaseOrderStoreUnderTest.getPurchaseOrder("orderId"));
        verify(spyResponseInputStream).close();
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetPurchaseOrder_S3ClientThrowsNoSuchKeyException() throws Exception {
        // Setup
        when(mockS3Client.getObject(GetObjectRequest.builder()
                .bucket("bucketName")
                .key("key")
                .build())).thenThrow(NoSuchKeyException.class);

        // Run the test
        final PDDocument result = purchaseOrderStoreUnderTest.getPurchaseOrder("orderId");

        // Verify the results
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetPurchaseOrder_S3ClientThrowsAwsServiceException() throws Exception {
        // Setup
        when(mockS3Client.getObject(GetObjectRequest.builder()
                .bucket("bucketName")
                .key("key")
                .build())).thenThrow(AwsServiceException.class);

        // Run the test
        final PDDocument result = purchaseOrderStoreUnderTest.getPurchaseOrder("orderId");

        // Verify the results
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetPurchaseOrder_S3ClientThrowsSdkClientException() throws Exception {
        // Setup
        when(mockS3Client.getObject(GetObjectRequest.builder()
                .bucket("bucketName")
                .key("key")
                .build())).thenThrow(SdkClientException.class);

        // Run the test
        final PDDocument result = purchaseOrderStoreUnderTest.getPurchaseOrder("orderId");

        // Verify the results
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetPurchaseOrder_S3ClientThrowsS3Exception() throws Exception {
        // Setup
        when(mockS3Client.getObject(GetObjectRequest.builder()
                .bucket("bucketName")
                .key("key")
                .build())).thenThrow(S3Exception.class);

        // Run the test
        final PDDocument result = purchaseOrderStoreUnderTest.getPurchaseOrder("orderId");

        // Verify the results
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }
}
              
            
Generated Test Class
<
AWS SDK V1 DynamoDBMapper
The source class is a component that retrieves orders from a DynamoDB table. The test class generated by Squaretest contains tests for the following scenarios.
  • The primary flow where the table contains the order.
  • The alternate flow where the table does not contain the order.
  • The alternate flow where the order could not be retrieved due to a network error or service error.
                
package com.squaretest.demo11;

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import org.apache.commons.lang3.Validate;

public class OrderStore {

    private final DynamoDBMapper dynamoDBMapper;

    public OrderStore(final DynamoDBMapper dynamoDBMapper) {
        this.dynamoDBMapper = dynamoDBMapper;
    }

    public Order getOrder(final String orderId) throws OrderStoreException {
        Validate.notBlank(orderId, "Orderid cannot be blank");

        // Make the service call.
        final Order order;
        try {
            order = dynamoDBMapper.load(Order.class, orderId);
        } catch (final Exception e) {
            throw new OrderStoreException(e);
        }

        // Validate the order.
        if (order == null) {
            throw new OrderStoreException("Order with ID " + orderId + " not found.");
        }
        return order;
    }
}
                
              
Source Class
>
              
package com.squaretest.demo11;

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.math.BigDecimal;
import java.util.List;

import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class OrderStoreTest {

    @Mock
    private DynamoDBMapper mockDynamoDBMapper;

    private OrderStore orderStoreUnderTest;

    @BeforeEach
    void setUp() {
        orderStoreUnderTest = new OrderStore(mockDynamoDBMapper);
    }

    @Test
    void testGetOrder() throws Exception {
        // Setup

        // Configure DynamoDBMapper.load(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(new DateTime(2020, 1, 1, 1, 0, 0, 0));
        final Product product = new Product();
        product.setId("id");
        product.setName("name");
        product.setPrice(new BigDecimal("0.00"));
        order.setProducts(List.of(product));
        when(mockDynamoDBMapper.load(Order.class, "hashKey")).thenReturn(order);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDBMapperReturnsNull() throws Exception {
        // Setup
        when(mockDynamoDBMapper.load(Order.class, "hashKey")).thenReturn(null);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDBMapperThrowsAmazonDynamoDBException() throws Exception {
        // Setup
        when(mockDynamoDBMapper.load(Order.class, "hashKey")).thenThrow(AmazonDynamoDBException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }
}
              
            
Generated Test Class
<
AWS SDK V2 DynamoDBMapper
The source class is a component that retrieves orders from a DynamoDB table. The test class generated by Squaretest contains tests for the following scenarios.
  • The primary flow where the table contains the order.
  • The alternate flow where the table does not contain the order.
  • The alternate flow where the order could not be retrieved due to a network error.
  • The alternate flow where the order could not be retrieved due to a service error.
                
package com.squaretest.demo12;

import org.apache.commons.lang3.Validate;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Key;

public class OrderStore {

    private final DynamoDbTable<Order> ordersTable;

    public OrderStore(final DynamoDbTable<Order> ordersTable) {
        this.ordersTable = ordersTable;
    }

    public Order getOrder(final String orderId) throws OrderStoreException {
        Validate.notBlank(orderId, "Orderid cannot be blank");

        // Make the service call.
        final Order order;
        try {
            order = ordersTable.getItem(Key.builder().partitionValue(orderId).build());
        } catch (final Exception e) {
            throw new OrderStoreException(e);
        }

        // Validate the order.
        if (order == null) {
            throw new OrderStoreException("Order with ID " + orderId + " not found.");
        }
        return order;
    }
}
                
              
Source Class
>
              
package com.squaretest.demo12;

import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Key;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;

import java.math.BigDecimal;
import java.util.List;

import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class OrderStoreTest {

    @Mock
    private DynamoDbTable<Order> mockOrdersTable;

    private OrderStore orderStoreUnderTest;

    @BeforeEach
    void setUp() {
        orderStoreUnderTest = new OrderStore(mockOrdersTable);
    }

    @Test
    void testGetOrder() throws Exception {
        // Setup

        // Configure DynamoDbTable.getItem(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(new DateTime(2020, 1, 1, 1, 0, 0, 0));
        final Product product = new Product();
        product.setId("id");
        product.setName("name");
        product.setPrice(new BigDecimal("0.00"));
        order.setProducts(List.of(product));
        when(mockOrdersTable.getItem(Key.builder()
                .partitionValue("partitionKey")
                .sortValue("sortKey")
                .build())).thenReturn(order);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDbTableReturnsNull() throws Exception {
        // Setup
        when(mockOrdersTable.getItem(Key.builder()
                .partitionValue("partitionKey")
                .sortValue("sortKey")
                .build())).thenReturn(null);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDbTableThrowsSdkClientException() throws Exception {
        // Setup
        when(mockOrdersTable.getItem(Key.builder()
                .partitionValue("partitionKey")
                .sortValue("sortKey")
                .build())).thenThrow(SdkClientException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDbTableThrowsDynamoDbException() throws Exception {
        // Setup
        when(mockOrdersTable.getItem(Key.builder()
                .partitionValue("partitionKey")
                .sortValue("sortKey")
                .build())).thenThrow(DynamoDbException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }
}
              
            
Generated Test Class
<
AWS SDK V1 DynamoDBClient
The source class is a component that retrieves orders from a DynamoDB table. The test class generated by Squaretest contains tests for the following scenarios.
  • The primary flow where the table contains the order.
  • The alternate flow where the table does not contain the order.
  • The alternate flow where the request exceeded the provisioned throughput for the DynamoDB Table.
  • The alternate flow where the request exceeds the total number of requests allowed by the AWS account.
  • The alternate flow where the DynamoDB returns an internal service error.
                
package com.squaretest.demo14;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.GetItemRequest;
import com.amazonaws.services.dynamodbv2.model.GetItemResult;
import org.apache.commons.lang3.Validate;

import java.util.Map;

public class OrderStore {

    private final AmazonDynamoDB dynamoDb;
    private final String ordersTableName;

    public OrderStore(final AmazonDynamoDB dynamoDb, final String ordersTableName) {
        this.dynamoDb = dynamoDb;
        this.ordersTableName = ordersTableName;
    }

    public Order getOrder(final String orderId) throws OrderStoreException {
        Validate.notBlank(orderId, "Orderid cannot be blank");

        // Make the service call.
        final GetItemResult result;
        try {
            result = dynamoDb.getItem(new GetItemRequest(ordersTableName, Map.of("OrderId", new AttributeValue(orderId))));
        } catch (final Exception e) {
            throw new OrderStoreException(e);
        }

        // Unmarshall the result into an Order object.
        final Map<String, AttributeValue> orderData = result.getItem();
        return unmarshall(orderId, orderData);
    }

    private static Order unmarshall(final String orderId, final Map<String, AttributeValue> orderData) throws OrderStoreException {
        if (orderData == null) {
            throw new OrderStoreException("Order with ID " + orderId + " not found.");
        }
        // Code to transform the orderData into an Order object omitted.
        return new Order();
    }
}

                
              
Source Class
>
              
package com.squaretest.demo14;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.model.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Map;

import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class OrderStoreTest {

    @Mock
    private AmazonDynamoDB mockDynamoDb;

    private OrderStore orderStoreUnderTest;

    @BeforeEach
    void setUp() {
        orderStoreUnderTest = new OrderStore(mockDynamoDb, "ordersTableName");
    }

    @Test
    void testGetOrder() throws Exception {
        // Setup

        // Configure AmazonDynamoDB.getItem(...).
        final GetItemResult getItemResult = new GetItemResult().withItem(Map.ofEntries(
                Map.entry("PrimaryKeyName", new AttributeValue().withS("PrimaryKeyValue")),
                Map.entry("KeyName2", new AttributeValue().withS("Value2"))
        ));
        when(mockDynamoDb.getItem(new GetItemRequest("TableName",
                Map.of("PrimaryKeyName", new AttributeValue().withS("PrimaryKeyValue"))
        ))).thenReturn(getItemResult);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_AmazonDynamoDBReturnsNoItem() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(new GetItemRequest("TableName",
                Map.of("PrimaryKeyName", new AttributeValue().withS("PrimaryKeyValue"))
        ))).thenReturn(new GetItemResult());

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_AmazonDynamoDBThrowsProvisionedThroughputExceededException() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(new GetItemRequest("TableName",
                Map.of("PrimaryKeyName", new AttributeValue().withS("PrimaryKeyValue"))
        ))).thenThrow(ProvisionedThroughputExceededException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_AmazonDynamoDBThrowsResourceNotFoundException() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(new GetItemRequest("TableName",
                Map.of("PrimaryKeyName", new AttributeValue().withS("PrimaryKeyValue"))
        ))).thenThrow(ResourceNotFoundException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_AmazonDynamoDBThrowsRequestLimitExceededException() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(new GetItemRequest("TableName",
                Map.of("PrimaryKeyName", new AttributeValue().withS("PrimaryKeyValue"))
        ))).thenThrow(RequestLimitExceededException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_AmazonDynamoDBThrowsInternalServerErrorException() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(new GetItemRequest("TableName",
                Map.of("PrimaryKeyName", new AttributeValue().withS("PrimaryKeyValue"))
        ))).thenThrow(InternalServerErrorException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }
}
              
            
Generated Test Class
<
AWS SDK V2 DynamoDBClient
The source class is a component that retrieves orders from a DynamoDB table. The test class generated by Squaretest contains tests for the same scenarios described in The AWS SDK V1 DynamoDBClient.
                
package com.squaretest.demo15;

import org.apache.commons.lang3.Validate;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import software.amazon.awssdk.services.dynamodb.model.GetItemResponse;

import java.util.Map;

public class OrderStore {

    private final DynamoDbClient dynamoDb;
    private final String ordersTableName;

    public OrderStore(final DynamoDbClient dynamoDb, final String ordersTableName) {
        this.dynamoDb = dynamoDb;
        this.ordersTableName = ordersTableName;
    }

    public Order getOrder(final String orderId) throws OrderStoreException {
        Validate.notBlank(orderId, "Orderid cannot be blank");

        // Make the service call.
        final GetItemResponse result;
        try {
            result = dynamoDb.getItem(GetItemRequest.builder().tableName(ordersTableName).key(Map.of("OrderId", AttributeValue.builder().s(orderId).build())).build());
        } catch (final Exception e) {
            throw new OrderStoreException(e);
        }

        // Unmarshall the result into an Order object.
        return unmarshall(orderId, result);
    }

    private static Order unmarshall(final String orderId, final GetItemResponse orderData) throws OrderStoreException {
        if (!orderData.hasItem()) {
            throw new OrderStoreException("Order with ID " + orderId + " not found.");
        }
        // Code to transform the orderData into an Order object omitted.
        return new Order();
    }
}
                
              
Source Class
>
              
package com.squaretest.demo15;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import software.amazon.awssdk.awscore.exception.AwsServiceException;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.*;

import java.util.Map;

import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class OrderStoreTest {

    @Mock
    private DynamoDbClient mockDynamoDb;

    private OrderStore orderStoreUnderTest;

    @BeforeEach
    void setUp() {
        orderStoreUnderTest = new OrderStore(mockDynamoDb, "ordersTableName");
    }

    @Test
    void testGetOrder() throws Exception {
        // Setup

        // Configure DynamoDbClient.getItem(...).
        final GetItemResponse getItemResponse = GetItemResponse.builder()
                .item(Map.ofEntries(
                        Map.entry("PrimaryKeyName", AttributeValue.builder().s("PrimaryKeyValue").build()),
                        Map.entry("OtherKeyName", AttributeValue.builder().s("OtherKeyValue").build())
                )).build();
        when(mockDynamoDb.getItem(GetItemRequest.builder()
                .tableName("TableName")
                .key(Map.of("PrimaryKeyName", AttributeValue.builder().s("PrimaryKeyValue").build()))
                .build())).thenReturn(getItemResponse);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDbClientReturnsNoItem() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(GetItemRequest.builder()
                .tableName("TableName")
                .key(Map.of("PrimaryKeyName", AttributeValue.builder().s("PrimaryKeyValue").build()))
                .build())).thenReturn(GetItemResponse.builder().build());

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDbClientThrowsProvisionedThroughputExceededException() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(GetItemRequest.builder()
                .tableName("TableName")
                .key(Map.of("PrimaryKeyName", AttributeValue.builder().s("PrimaryKeyValue").build()))
                .build())).thenThrow(ProvisionedThroughputExceededException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDbClientThrowsResourceNotFoundException() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(GetItemRequest.builder()
                .tableName("TableName")
                .key(Map.of("PrimaryKeyName", AttributeValue.builder().s("PrimaryKeyValue").build()))
                .build())).thenThrow(ResourceNotFoundException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDbClientThrowsRequestLimitExceededException() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(GetItemRequest.builder()
                .tableName("TableName")
                .key(Map.of("PrimaryKeyName", AttributeValue.builder().s("PrimaryKeyValue").build()))
                .build())).thenThrow(RequestLimitExceededException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDbClientThrowsInternalServerErrorException() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(GetItemRequest.builder()
                .tableName("TableName")
                .key(Map.of("PrimaryKeyName", AttributeValue.builder().s("PrimaryKeyValue").build()))
                .build())).thenThrow(InternalServerErrorException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDbClientThrowsAwsServiceException() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(GetItemRequest.builder()
                .tableName("TableName")
                .key(Map.of("PrimaryKeyName", AttributeValue.builder().s("PrimaryKeyValue").build()))
                .build())).thenThrow(AwsServiceException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDbClientThrowsSdkClientException() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(GetItemRequest.builder()
                .tableName("TableName")
                .key(Map.of("PrimaryKeyName", AttributeValue.builder().s("PrimaryKeyValue").build()))
                .build())).thenThrow(SdkClientException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }

    @Test
    void testGetOrder_DynamoDbClientThrowsDynamoDbException() throws Exception {
        // Setup
        when(mockDynamoDb.getItem(GetItemRequest.builder()
                .tableName("TableName")
                .key(Map.of("PrimaryKeyName", AttributeValue.builder().s("PrimaryKeyValue").build()))
                .build())).thenThrow(DynamoDbException.class);

        // Run the test
        final Order result = orderStoreUnderTest.getOrder("orderId");

        // Verify the results
    }
}
              
            
Generated Test Class
<
AWS SDK V2 Comprehend
The source class is a component that uses Amazon Comprehend to retrieve the list of entities mentioned in the provided text. The test class generated by Squaretest contains tests for the following scenarios.
  • The primary flow where the service returns a response with one entity.
  • The alternate flow where the service returns a response indicating the request was invalid.
  • The alternate flow where the service returns a response indicating the resource specified in the request was not available.
  • The alternate flow where the text specified in the request was too large.
  • The alternate flow where an internal service error occurred while processing the request.
  • The alternate flow where the connection was interrupted while making the request.
                
package com.squaretest.demo18;

import org.apache.commons.lang3.StringUtils;
import software.amazon.awssdk.services.comprehend.ComprehendClient;
import software.amazon.awssdk.services.comprehend.model.DetectEntitiesRequest;
import software.amazon.awssdk.services.comprehend.model.DetectEntitiesResponse;
import software.amazon.awssdk.services.comprehend.model.Entity;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class LanguageAnalyzer {

    private final ComprehendClient comService;

    public LanguageAnalyzer(final ComprehendClient comService) {
        this.comService = comService;
    }

    public List<String> getEntitiesMentioned(final String text) throws LanguageServiceException {
        if(StringUtils.isBlank(text)) {
            return Collections.emptyList();
        }

        // Make the service call.
        final DetectEntitiesRequest detectEntitiesRequest = DetectEntitiesRequest.builder()
                .text(text)
                .languageCode("en")
                .build();
        final DetectEntitiesResponse detectEntitiesResult;
        try {
            detectEntitiesResult = comService.detectEntities(detectEntitiesRequest);
        } catch(final Exception e) {
            throw new LanguageServiceException("Exception querying Amazon Comprehend service.", e);
        }

        // Return the entities mentioned.
        return detectEntitiesResult.entities().stream().map(Entity::text).collect(Collectors.toList());
    }
}
                
              
Source Class
>
              
package com.squaretest.demo18;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import software.amazon.awssdk.awscore.exception.AwsServiceException;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.services.comprehend.ComprehendClient;
import software.amazon.awssdk.services.comprehend.model.*;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class LanguageAnalyzerTest {

    @Mock
    private ComprehendClient mockComService;

    private LanguageAnalyzer languageAnalyzerUnderTest;

    @BeforeEach
    void setUp() {
        languageAnalyzerUnderTest = new LanguageAnalyzer(mockComService);
    }

    @Test
    void testGetEntitiesMentioned() throws Exception {
        // Setup

        // Configure ComprehendClient.detectEntities(...).
        final DetectEntitiesResponse detectEntitiesResponse = DetectEntitiesResponse.builder()
                .entities(Entity.builder()
                        .score(0.0f)
                        .type(EntityType.PERSON)
                        .text("text")
                        .beginOffset(0)
                        .endOffset(0)
                        .build())
                .build();
        when(mockComService.detectEntities(DetectEntitiesRequest.builder()
                .text("text")
                .languageCode(LanguageCode.EN)
                .endpointArn("endpointArn")
                .build())).thenReturn(detectEntitiesResponse);

        // Run the test
        final List<String> result = languageAnalyzerUnderTest.getEntitiesMentioned("text");

        // Verify the results
        assertEquals(List.of("value"), result);
    }

    @Test
    void testGetEntitiesMentioned_ComprehendClientThrowsInvalidRequestException() throws Exception {
        // Setup
        when(mockComService.detectEntities(DetectEntitiesRequest.builder()
                .text("text")
                .languageCode(LanguageCode.EN)
                .endpointArn("endpointArn")
                .build())).thenThrow(InvalidRequestException.class);

        // Run the test
        final List<String> result = languageAnalyzerUnderTest.getEntitiesMentioned("text");

        // Verify the results
        assertEquals(List.of("value"), result);
    }

    @Test
    void testGetEntitiesMentioned_ComprehendClientThrowsResourceUnavailableException() throws Exception {
        // Setup
        when(mockComService.detectEntities(DetectEntitiesRequest.builder()
                .text("text")
                .languageCode(LanguageCode.EN)
                .endpointArn("endpointArn")
                .build())).thenThrow(ResourceUnavailableException.class);

        // Run the test
        final List<String> result = languageAnalyzerUnderTest.getEntitiesMentioned("text");

        // Verify the results
        assertEquals(List.of("value"), result);
    }

    @Test
    void testGetEntitiesMentioned_ComprehendClientThrowsTextSizeLimitExceededException() throws Exception {
        // Setup
        when(mockComService.detectEntities(DetectEntitiesRequest.builder()
                .text("text")
                .languageCode(LanguageCode.EN)
                .endpointArn("endpointArn")
                .build())).thenThrow(TextSizeLimitExceededException.class);

        // Run the test
        final List<String> result = languageAnalyzerUnderTest.getEntitiesMentioned("text");

        // Verify the results
        assertEquals(List.of("value"), result);
    }

    @Test
    void testGetEntitiesMentioned_ComprehendClientThrowsUnsupportedLanguageException() throws Exception {
        // Setup
        when(mockComService.detectEntities(DetectEntitiesRequest.builder()
                .text("text")
                .languageCode(LanguageCode.EN)
                .endpointArn("endpointArn")
                .build())).thenThrow(UnsupportedLanguageException.class);

        // Run the test
        final List<String> result = languageAnalyzerUnderTest.getEntitiesMentioned("text");

        // Verify the results
        assertEquals(List.of("value"), result);
    }

    @Test
    void testGetEntitiesMentioned_ComprehendClientThrowsInternalServerException() throws Exception {
        // Setup
        when(mockComService.detectEntities(DetectEntitiesRequest.builder()
                .text("text")
                .languageCode(LanguageCode.EN)
                .endpointArn("endpointArn")
                .build())).thenThrow(InternalServerException.class);

        // Run the test
        final List<String> result = languageAnalyzerUnderTest.getEntitiesMentioned("text");

        // Verify the results
        assertEquals(List.of("value"), result);
    }

    @Test
    void testGetEntitiesMentioned_ComprehendClientThrowsAwsServiceException() throws Exception {
        // Setup
        when(mockComService.detectEntities(DetectEntitiesRequest.builder()
                .text("text")
                .languageCode(LanguageCode.EN)
                .endpointArn("endpointArn")
                .build())).thenThrow(AwsServiceException.class);

        // Run the test
        final List<String> result = languageAnalyzerUnderTest.getEntitiesMentioned("text");

        // Verify the results
        assertEquals(List.of("value"), result);
    }

    @Test
    void testGetEntitiesMentioned_ComprehendClientThrowsSdkClientException() throws Exception {
        // Setup
        when(mockComService.detectEntities(DetectEntitiesRequest.builder()
                .text("text")
                .languageCode(LanguageCode.EN)
                .endpointArn("endpointArn")
                .build())).thenThrow(SdkClientException.class);

        // Run the test
        final List<String> result = languageAnalyzerUnderTest.getEntitiesMentioned("text");

        // Verify the results
        assertEquals(List.of("value"), result);
    }

    @Test
    void testGetEntitiesMentioned_ComprehendClientThrowsComprehendException() throws Exception {
        // Setup
        when(mockComService.detectEntities(DetectEntitiesRequest.builder()
                .text("text")
                .languageCode(LanguageCode.EN)
                .endpointArn("endpointArn")
                .build())).thenThrow(ComprehendException.class);

        // Run the test
        final List<String> result = languageAnalyzerUnderTest.getEntitiesMentioned("text");

        // Verify the results
        assertEquals(List.of("value"), result);
    }
}
              
            
Generated Test Class
<
Google Cloud Storage
The source class is a component that retrieves purchase orders from a Google Cloud Storage bucket. The test class generated by Squaretest contains tests for the following scenarios.
  • The primary flow where the bucket contains the purchase order.
  • The alternate flow where an error occurs while downloading the purchase order.
                
package com.squaretest.demo16;

import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageException;
import org.apache.commons.lang3.Validate;
import org.apache.pdfbox.pdmodel.PDDocument;

import java.io.IOException;

public class PurchaseOrderStore {

    private static final String PathFormat = "%s/purchaseOrder.pdf";

    private final Storage storage;
    private final MetricAdapter metricAdapter;
    private final String bucketName;

    public PurchaseOrderStore(
            final Storage storage,
            final MetricAdapter metricAdapter,
            final String bucketName) {
        this.storage = storage;
        this.metricAdapter = metricAdapter;
        this.bucketName = bucketName;
    }

    public PDDocument getPurchaseOrder(final String orderId) throws PurchaseOrderStoreException {
        Validate.notBlank(orderId, "Orderid cannot be blank");
        final String path = String.format(PathFormat, orderId);
        try {
            final byte[] content = storage.readAllBytes(bucketName, path);
            final PDDocument purchaseOrderDoc = PDDocument.load(content);
            metricAdapter.recordEvent(MetricEvent.Success);
            return purchaseOrderDoc;
        } catch (final StorageException e) {
            metricAdapter.recordEvent(MetricEvent.StorageException);
            throw new PurchaseOrderStoreException(
                    String.format("StorageException while downloading object with path: %s", path), e);
        } catch (final IOException e) {
            metricAdapter.recordEvent(MetricEvent.IOException);
            throw new PurchaseOrderStoreException(
                    String.format("IOException while parsing object with path: %s", path), e);
        }
    }
}
                
              
Source Class
>
              
package com.squaretest.demo16;

import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class PurchaseOrderStoreTest {

    @Mock
    private Storage mockStorage;
    @Mock
    private MetricAdapter mockMetricAdapter;

    private PurchaseOrderStore purchaseOrderStoreUnderTest;

    @BeforeEach
    void setUp() {
        purchaseOrderStoreUnderTest = new PurchaseOrderStore(mockStorage, mockMetricAdapter, "bucketName");
    }

    @Test
    void testGetPurchaseOrder() throws Exception {
        // Setup
        when(mockStorage.readAllBytes("bucket", "blob", Storage.BlobSourceOption.generationMatch(0L))).thenReturn("content".getBytes());

        // Run the test
        final PDDocument result = purchaseOrderStoreUnderTest.getPurchaseOrder("orderId");

        // Verify the results
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetPurchaseOrder_StorageThrowsStorageException() throws Exception {
        // Setup
        when(mockStorage.readAllBytes("bucket", "blob", Storage.BlobSourceOption.generationMatch(0L))).thenThrow(StorageException.class);

        // Run the test
        final PDDocument result = purchaseOrderStoreUnderTest.getPurchaseOrder("orderId");

        // Verify the results
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }
}
              
            
Generated Test Class
<
Google Cloud Natural Language
The source class is a component that uses Google Cloud Natural Language to retrieve the list of entities mentioned in the provided text. The test class generated by Squaretest contains tests for the following scenarios.
  • The primary flow where the service returns a response with one entity.
  • The alternate flow where the service returns an error.
                
package com.squaretest.demo17;

import com.google.cloud.language.v1.*;
import org.apache.commons.lang3.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class LanguageAnalyzer {

    private final LanguageServiceClient languageService;

    public LanguageAnalyzer(final LanguageServiceClient languageService) {
        this.languageService = languageService;
    }

    public List<String> getEntitiesMentioned(final String text) throws LanguageServiceException {
        if(StringUtils.isBlank(text)) {
            return Collections.emptyList();
        }

        // Make the service call.
        final AnalyzeEntitiesResponse response;
        try {
            final Document doc = Document.newBuilder().setContent(text).setType(Document.Type.PLAIN_TEXT).build();
            final AnalyzeEntitiesRequest request =
                    AnalyzeEntitiesRequest.newBuilder()
                            .setDocument(doc)
                            .setEncodingType(EncodingType.UTF16)
                            .build();
            response = languageService.analyzeEntities(request);
        } catch(final Exception e) {
            throw new LanguageServiceException("Exception querying Google Cloud Natural Language Service.", e);
        }

        // Return the entities mentioned.
        return response.getEntitiesList().stream().map(Entity::getName).collect(Collectors.toList());
    }
}
                
              
Source Class
>
              
package com.squaretest.demo17;

import com.google.api.gax.rpc.ApiException;
import com.google.cloud.language.v1.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class LanguageAnalyzerTest {

    @Mock
    private LanguageServiceClient mockLanguageService;

    private LanguageAnalyzer languageAnalyzerUnderTest;

    @BeforeEach
    void setUp() {
        languageAnalyzerUnderTest = new LanguageAnalyzer(mockLanguageService);
    }

    @Test
    void testGetEntitiesMentioned() throws Exception {
        // Setup

        // Configure LanguageServiceClient.analyzeEntities(...).
        final AnalyzeEntitiesResponse analyzeEntitiesResponse = AnalyzeEntitiesResponse.newBuilder()
                .addEntities(Entity.newBuilder()
                        .setName("value")
                        .setType(Entity.Type.UNKNOWN)
                        .putMetadata("key", "value")
                        .setSalience(0.0f)
                        .addMentions(EntityMention.newBuilder()
                                .setText(TextSpan.newBuilder()
                                        .setContent("value")
                                        .setBeginOffset(0)
                                        .build())
                                .setType(EntityMention.Type.TYPE_UNKNOWN)
                                .setSentiment(Sentiment.newBuilder()
                                        .setMagnitude(0.0f)
                                        .setScore(0.0f)
                                        .build())
                                .build())
                        .setSentiment(Sentiment.newBuilder()
                                .setMagnitude(0.0f)
                                .setScore(0.0f)
                                .build())
                        .build())
                .setLanguage("value")
                .build();
        when(mockLanguageService.analyzeEntities(AnalyzeEntitiesRequest.newBuilder()
                .setDocument(Document.newBuilder()
                        .setType(Document.Type.TYPE_UNSPECIFIED)
                        .setContent("value")
                        .setGcsContentUri("value")
                        .setLanguage("value")
                        .build())
                .setEncodingType(EncodingType.NONE)
                .build())).thenReturn(analyzeEntitiesResponse);

        // Run the test
        final List<String> result = languageAnalyzerUnderTest.getEntitiesMentioned("text");

        // Verify the results
        assertEquals(List.of("value"), result);
    }

    @Test
    void testGetEntitiesMentioned_LanguageServiceClientThrowsApiException() throws Exception {
        // Setup
        when(mockLanguageService.analyzeEntities(AnalyzeEntitiesRequest.newBuilder()
                .setDocument(Document.newBuilder()
                        .setType(Document.Type.TYPE_UNSPECIFIED)
                        .setContent("value")
                        .setGcsContentUri("value")
                        .setLanguage("value")
                        .build())
                .setEncodingType(EncodingType.NONE)
                .build())).thenThrow(ApiException.class);

        // Run the test
        final List<String> result = languageAnalyzerUnderTest.getEntitiesMentioned("text");

        // Verify the results
        assertEquals(List.of("value"), result);
    }
}
              
            
Generated Test Class
<
Spring Rest Controller
The source class is a rest controller that retrieves deals from a deals service and returns them in JSON form to the requester. The test class generated by Squaretest contains tests for the following scenarios.
  • The primary flow where the deals service returns one item.
  • The alternate flow where the deals service returns no items.
  • The alternate flow where the deals service returns an error.
  • The alternate flow where the connection to the deals service was interrupted.
                
package com.squaretest.demo4;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.List;

@RestController
@RequestMapping(path = "/deals", produces = MediaType.APPLICATION_JSON_VALUE)
public class DealsController {

    private final DealsProvider dealsProvider;
    private final MetricAdapter metricAdapter;

    public DealsController(
            final DealsProvider dealsProvider,
            final MetricAdapter metricAdapter) {
        this.dealsProvider = dealsProvider;
        this.metricAdapter = metricAdapter;
    }

    @GetMapping("/current")
    public List<Deal> getCurrentDeals(@RequestParam(name = "sortKey") final String sortKey) {
        return safeGetDeals(sortKey);
    }

    private List<Deal> safeGetDeals(final String sortKey) {
        try {
            final List<Deal> deals = dealsProvider.getCurrentDeals(sortKey);
            metricAdapter.recordEvent(MetricEvent.Success);
            return deals;
        } catch (final NetworkException e) {
            metricAdapter.recordEvent(MetricEvent.NetworkError);
            return Collections.emptyList();
        } catch (final ServiceException e) {
            metricAdapter.recordEvent(MetricEvent.ServiceError);
            return Collections.emptyList();
        }
    }
}
                
              
Source Class
>
              
package com.squaretest.demo4;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@ExtendWith(SpringExtension.class)
@WebMvcTest(DealsController.class)
class DealsControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private DealsProvider mockDealsProvider;
    @MockBean
    private MetricAdapter mockMetricAdapter;

    @Test
    void testGetCurrentDeals() throws Exception {
        // Setup

        // Configure DealsProvider.getCurrentDeals(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        final List<Deal> deals = List.of(deal);
        when(mockDealsProvider.getCurrentDeals("sortKey")).thenReturn(deals);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/deals/current")
                .param("sortKey", "sortKey")
                .accept(MediaType.APPLICATION_JSON))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetCurrentDeals_DealsProviderReturnsNoItems() throws Exception {
        // Setup
        when(mockDealsProvider.getCurrentDeals("sortKey")).thenReturn(Collections.emptyList());

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/deals/current")
                .param("sortKey", "sortKey")
                .accept(MediaType.APPLICATION_JSON))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetCurrentDeals_DealsProviderThrowsNetworkException() throws Exception {
        // Setup
        when(mockDealsProvider.getCurrentDeals("sortKey")).thenThrow(NetworkException.class);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/deals/current")
                .param("sortKey", "sortKey")
                .accept(MediaType.APPLICATION_JSON))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }

    @Test
    void testGetCurrentDeals_DealsProviderThrowsServiceException() throws Exception {
        // Setup
        when(mockDealsProvider.getCurrentDeals("sortKey")).thenThrow(ServiceException.class);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/deals/current")
                .param("sortKey", "sortKey")
                .accept(MediaType.APPLICATION_JSON))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
        verify(mockMetricAdapter).recordEvent(MetricEvent.Success);
    }
}
              
            
Generated Test Class
<
Spring Website Controller
The source class is a controller that renders pages allowing admin users to view and create deals. Squaretest generated the following tests for the List Deals page.
  • The primary flow where the deals service returns one item.
  • The alternate flow where the deals service returns no items.
  • The alternate flow where the deals service returns an error.
  • The alternate flow where the connection to the deals service was interrupted.
Squaretest generated the following tests for the Create Deals page.
  • The primary flow where the new deal is created successfully.
  • The alternate flow where the deals service returns an error.
  • The alternate flow where the connection to the deals service was interrupted.
                
package com.squaretest.demo5;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

@Controller
@RequestMapping(path = "/admin/deals")
public class DealsController {

    private static final Logger Log = Logger.getLogger(DealsController.class.getName());

    private final DealsStore dealsStore;

    public DealsController(
            final DealsStore dealsStore) {
        this.dealsStore = dealsStore;
    }

    @GetMapping
    public String list(Model model) throws NetworkException, ServiceException {
        model.addAttribute("deals", getDeals());
        return "admin/deals/index";
    }


    @GetMapping("/new")
    public String newDeal(Model model) {
        DealForm emptyDeal = new DealForm();
        model.addAttribute("deal", emptyDeal);
        return "admin/deals/new";
    }

    @PostMapping("/new")
    public String createNewDeal(@Valid DealForm dealForm, Model model) throws NetworkException, ServiceException {
        Deal deal = new Deal();
        mapProperties(dealForm, deal);
        try {
            this.dealsStore.save(deal);
        } catch (NetworkException | ServiceException e) {
            Log.log(Level.SEVERE, "Exception saving deal", e);
            throw e;
        }
        return "redirect:/admin/deals";
    }

    private List<Deal> getDeals() throws NetworkException, ServiceException {
        try {
            return dealsStore.getCurrentDeals();
        } catch (final NetworkException | ServiceException e) {
            Log.log(Level.SEVERE, "Exception retrieving deals from deals service", e);
            throw e;
        }
    }

    private static void mapProperties(final DealForm dealForm, final Deal deal) {
        // Omitted: code to read properties dealForm and set them on deal.
    }
}
                
              
Source Class
>
              
package com.squaretest.demo5;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;

@ExtendWith(SpringExtension.class)
@WebMvcTest(DealsController.class)
class DealsControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private DealsStore mockDealsStore;

    @Test
    void testList() throws Exception {
        // Setup

        // Configure DealsStore.getCurrentDeals(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        final List<Deal> deals = List.of(deal);
        when(mockDealsStore.getCurrentDeals()).thenReturn(deals);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/admin/deals")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testList_DealsStoreReturnsNoItems() throws Exception {
        // Setup
        when(mockDealsStore.getCurrentDeals()).thenReturn(Collections.emptyList());

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/admin/deals")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testList_DealsStoreThrowsNetworkException() throws Exception {
        // Setup
        when(mockDealsStore.getCurrentDeals()).thenThrow(NetworkException.class);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/admin/deals")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testList_DealsStoreThrowsServiceException() throws Exception {
        // Setup
        when(mockDealsStore.getCurrentDeals()).thenThrow(ServiceException.class);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/admin/deals")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testNewDeal() throws Exception {
        // Setup

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/admin/deals/new")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testCreateNewDeal() throws Exception {
        // Setup

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(post("/admin/deals/new")
                .param("id", "id")
                .param("productName", "productName")
                .param("price", "0")
                .param("quantityRemaining", "0")
                .param("imageUrl", "imageUrl")
                .with(csrf())
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
        verify(mockDealsStore).save(any(Deal.class));
    }

    @Test
    void testCreateNewDeal_DealsStoreThrowsNetworkException() throws Exception {
        // Setup
        doThrow(NetworkException.class).when(mockDealsStore).save(any(Deal.class));

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(post("/admin/deals/new")
                .param("id", "id")
                .param("productName", "productName")
                .param("price", "0")
                .param("quantityRemaining", "0")
                .param("imageUrl", "imageUrl")
                .with(csrf())
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testCreateNewDeal_DealsStoreThrowsServiceException() throws Exception {
        // Setup
        doThrow(ServiceException.class).when(mockDealsStore).save(any(Deal.class));

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(post("/admin/deals/new")
                .param("id", "id")
                .param("productName", "productName")
                .param("price", "0")
                .param("quantityRemaining", "0")
                .param("imageUrl", "imageUrl")
                .with(csrf())
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }
}
              
            
Generated Test Class
<
Spring Website Controller Async
The source class is a controller that renders the index page for an ecommerce website. The controller needs to make service calls to load the customer's most recent orders as well as the deals for that particular day. The controller makes the service calls in separate threads so they can run in parallel and reduce page load time. Squaretest creates tests for the following cases.
  • The primary flow where the deals service and order service both return one item.
  • The alternate flow where the deals service returns no items.
  • The alternate flow where the deals service returns an error.
  • The alternate flow where the order service returns no items.
  • The alternate flow where the order service returns an error.
                
package com.squaretest.demo10;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;

@Controller
@RequestMapping(path = "/")
public class IndexController {

    private static final Logger Log = Logger.getLogger(IndexController.class.getName());

    private final DealsServiceAsync dealsService;
    private final OrdersServiceAsync ordersService;

    public IndexController(
            final DealsServiceAsync dealsService,
            final OrdersServiceAsync ordersService) {
        this.dealsService = dealsService;
        this.ordersService = ordersService;
    }

    @GetMapping
    public String index(final Model model) {
        // Perform the service calls in background threads.
        final CompletableFuture<List<Deal>> dealsFuture = dealsService.getDeals();
        final CompletableFuture<List<Order>> recentOrdersFuture = ordersService.getRecentOrders(getCustomerId());

        // Wait for the calls to complete, and add the results to the model.
        try {
            model.addAttribute("deals", dealsFuture.get());
        } catch (ExecutionException | InterruptedException e) {
            Log.log(Level.WARNING, "Exception querying deals service", e);
        }
        try {
            model.addAttribute("recentOrders", recentOrdersFuture.get());
        } catch (final ExecutionException | InterruptedException e) {
            Log.log(Level.WARNING, "Exception querying ordering service", e);
        }

        return "index";
    }

    private String getCustomerId() {
        // Omitted: the authentication logic.
        return "customerId";
    }
}
                
              
Source Class
>
              
package com.squaretest.demo10;

import org.joda.time.DateTime;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@ExtendWith(SpringExtension.class)
@WebMvcTest(IndexController.class)
class IndexControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private DealsServiceAsync mockDealsService;
    @MockBean
    private OrdersServiceAsync mockOrdersService;

    @Test
    void testIndex() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        final CompletableFuture<List<Deal>> listCompletableFuture = CompletableFuture.completedFuture(List.of(deal));
        when(mockDealsService.getDeals()).thenReturn(listCompletableFuture);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(new DateTime(2020, 1, 1, 1, 0, 0, 0));
        final Product product = new Product();
        product.setId("id");
        product.setName("name");
        product.setPrice(new BigDecimal("0.00"));
        order.setProducts(List.of(product));
        final CompletableFuture<List<Order>> listCompletableFuture1 = CompletableFuture.completedFuture(List.of(order));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listCompletableFuture1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_DealsServiceAsyncReturnsNoItems() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final CompletableFuture<List<Deal>> listCompletableFuture = CompletableFuture.completedFuture(Collections.emptyList());
        when(mockDealsService.getDeals()).thenReturn(listCompletableFuture);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(new DateTime(2020, 1, 1, 1, 0, 0, 0));
        final Product product = new Product();
        product.setId("id");
        product.setName("name");
        product.setPrice(new BigDecimal("0.00"));
        order.setProducts(List.of(product));
        final CompletableFuture<List<Order>> listCompletableFuture1 = CompletableFuture.completedFuture(List.of(order));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listCompletableFuture1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_DealsServiceAsyncReturnsFailure() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final CompletableFuture<List<Deal>> listCompletableFuture = CompletableFuture.failedFuture(new Exception("message"));
        when(mockDealsService.getDeals()).thenReturn(listCompletableFuture);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(new DateTime(2020, 1, 1, 1, 0, 0, 0));
        final Product product = new Product();
        product.setId("id");
        product.setName("name");
        product.setPrice(new BigDecimal("0.00"));
        order.setProducts(List.of(product));
        final CompletableFuture<List<Order>> listCompletableFuture1 = CompletableFuture.completedFuture(List.of(order));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listCompletableFuture1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_OrdersServiceAsyncReturnsNoItems() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        final CompletableFuture<List<Deal>> listCompletableFuture = CompletableFuture.completedFuture(List.of(deal));
        when(mockDealsService.getDeals()).thenReturn(listCompletableFuture);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final CompletableFuture<List<Order>> listCompletableFuture1 = CompletableFuture.completedFuture(Collections.emptyList());
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listCompletableFuture1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_OrdersServiceAsyncReturnsFailure() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        final CompletableFuture<List<Deal>> listCompletableFuture = CompletableFuture.completedFuture(List.of(deal));
        when(mockDealsService.getDeals()).thenReturn(listCompletableFuture);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final CompletableFuture<List<Order>> listCompletableFuture1 = CompletableFuture.failedFuture(new Exception("message"));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listCompletableFuture1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }
}
              
            
Generated Test Class
<
Spring Website Controller Async with ListenableFuture
The source class is the same as the previous Spring Website Controller Async example but with components that return ListenableFutures from Google Guava instead of CompletableFutures. Squaretest creates tests for the following cases.
  • The primary flow where the deals service and order service both return one item.
  • The alternate flow where the deals service returns no items.
  • The alternate flow where the deals service returns an error.
  • The alternate flow where the order service returns no items.
  • The alternate flow where the order service returns an error.
                
package com.squaretest.demo21;

import com.google.common.util.concurrent.ListenableFuture;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;

@Controller
@RequestMapping(path = "/")
public class IndexController {

    private static final Logger Log = Logger.getLogger(IndexController.class.getName());

    private final DealsServiceAsync dealsService;
    private final OrdersServiceAsync ordersService;

    public IndexController(
            final DealsServiceAsync dealsService,
            final OrdersServiceAsync ordersService) {
        this.dealsService = dealsService;
        this.ordersService = ordersService;
    }

    @GetMapping
    public String index(final Model model) {
        // Perform the service calls in background threads.
        final ListenableFuture<List<Deal>> dealsFuture = dealsService.getDeals();
        final ListenableFuture<List<Order>> recentOrdersFuture = ordersService.getRecentOrders(getCustomerId());

        // Wait for the calls to complete, and add the results to the model.
        try {
            model.addAttribute("deals", dealsFuture.get());
        } catch (ExecutionException | InterruptedException e) {
            Log.log(Level.WARNING, "Exception querying deals service", e);
        }
        try {
            model.addAttribute("recentOrders", recentOrdersFuture.get());
        } catch (final ExecutionException | InterruptedException e) {
            Log.log(Level.WARNING, "Exception querying ordering service", e);
        }

        return "index";
    }

    private String getCustomerId() {
        // Omitted: the authentication logic.
        return "customerId";
    }
}
                
              
Source Class
>
              
package com.squaretest.demo21;

import com.google.common.util.concurrent.SettableFuture;
import org.joda.time.DateTime;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@ExtendWith(SpringExtension.class)
@WebMvcTest(IndexController.class)
class IndexControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private DealsServiceAsync mockDealsService;
    @MockBean
    private OrdersServiceAsync mockOrdersService;

    @Test
    void testIndex() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        final List<Deal> deals = List.of(deal);
        final SettableFuture<List<Deal>> listListenableFuture = SettableFuture.create();
        listListenableFuture.set(deals);
        when(mockDealsService.getDeals()).thenReturn(listListenableFuture);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(new DateTime(2020, 1, 1, 1, 0, 0, 0));
        final Product product = new Product();
        product.setId("id");
        product.setName("name");
        product.setPrice(new BigDecimal("0.00"));
        order.setProducts(List.of(product));
        final List<Order> orders = List.of(order);
        final SettableFuture<List<Order>> listListenableFuture1 = SettableFuture.create();
        listListenableFuture1.set(orders);
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listListenableFuture1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_DealsServiceAsyncReturnsNoItems() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final SettableFuture<List<Deal>> listListenableFuture = SettableFuture.create();
        listListenableFuture.set(Collections.emptyList());
        when(mockDealsService.getDeals()).thenReturn(listListenableFuture);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(new DateTime(2020, 1, 1, 1, 0, 0, 0));
        final Product product = new Product();
        product.setId("id");
        product.setName("name");
        product.setPrice(new BigDecimal("0.00"));
        order.setProducts(List.of(product));
        final List<Order> orders = List.of(order);
        final SettableFuture<List<Order>> listListenableFuture1 = SettableFuture.create();
        listListenableFuture1.set(orders);
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listListenableFuture1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_DealsServiceAsyncReturnsFailure() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final SettableFuture<List<Deal>> listListenableFuture = SettableFuture.create();
        listListenableFuture.setException(new Exception("message"));
        when(mockDealsService.getDeals()).thenReturn(listListenableFuture);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(new DateTime(2020, 1, 1, 1, 0, 0, 0));
        final Product product = new Product();
        product.setId("id");
        product.setName("name");
        product.setPrice(new BigDecimal("0.00"));
        order.setProducts(List.of(product));
        final List<Order> orders = List.of(order);
        final SettableFuture<List<Order>> listListenableFuture1 = SettableFuture.create();
        listListenableFuture1.set(orders);
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listListenableFuture1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_OrdersServiceAsyncReturnsNoItems() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        final List<Deal> deals = List.of(deal);
        final SettableFuture<List<Deal>> listListenableFuture = SettableFuture.create();
        listListenableFuture.set(deals);
        when(mockDealsService.getDeals()).thenReturn(listListenableFuture);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final SettableFuture<List<Order>> listListenableFuture1 = SettableFuture.create();
        listListenableFuture1.set(Collections.emptyList());
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listListenableFuture1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_OrdersServiceAsyncReturnsFailure() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        final List<Deal> deals = List.of(deal);
        final SettableFuture<List<Deal>> listListenableFuture = SettableFuture.create();
        listListenableFuture.set(deals);
        when(mockDealsService.getDeals()).thenReturn(listListenableFuture);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final SettableFuture<List<Order>> listListenableFuture1 = SettableFuture.create();
        listListenableFuture1.setException(new Exception("message"));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listListenableFuture1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }
}

              
            
Generated Test Class
<
Spring Website Controller Async with RxJava
The source class is the same as the previous Spring Website Controller Async example but with components that return Singles from RxJava instead of CompletableFutures. Squaretest creates tests for the following cases.
  • The primary flow where the deals service and order service both return one item.
  • The alternate flow where the deals service returns no items.
  • The alternate flow where the deals service does not return before the specified timeout.
  • The alternate flow where the deals service returns an error.
  • The alternate flow where the order service returns no items.
  • The alternate flow where the order service does not return before the specified timeout.
  • The alternate flow where the order service returns an error.
                
package com.squaretest.demo22;

import io.reactivex.rxjava3.core.Single;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;

@Controller
@RequestMapping(path = "/")
public class IndexController {

    private static final Logger Log = Logger.getLogger(IndexController.class.getName());

    private final DealsServiceAsync dealsService;
    private final OrdersServiceAsync ordersService;

    public IndexController(
            final DealsServiceAsync dealsService,
            final OrdersServiceAsync ordersService) {
        this.dealsService = dealsService;
        this.ordersService = ordersService;
    }

    @GetMapping
    public String index(final Model model) {
        // Perform the service calls in background threads.
        final Single<List<Deal>> dealsFuture = dealsService.getDeals()
                .timeout(1, TimeUnit.SECONDS,
                        Single.error(new TimeoutException("Timeout while querying deals service.")));
        final Single<List<Order>> recentOrdersFuture = ordersService.getRecentOrders(getCustomerId())
                .timeout(1, TimeUnit.SECONDS,
                        Single.error(new TimeoutException("Timeout while querying ordering service.")));

        // Wait for the calls to complete, and add the results to the model.
        try {
            model.addAttribute("deals", dealsFuture.blockingGet());
        } catch (RuntimeException e) {
            Log.log(Level.WARNING, "Exception querying deals service", e);
        }
        try {
            model.addAttribute("recentOrders", recentOrdersFuture.blockingGet());
        } catch (final RuntimeException e) {
            Log.log(Level.WARNING, "Exception querying ordering service", e);
        }

        return "index";
    }

    private String getCustomerId() {
        // Omitted: the authentication logic.
        return "customerId";
    }
}
                
              
Source Class
>
              
package com.squaretest.demo22;

import io.reactivex.rxjava3.core.Single;
import org.joda.time.DateTime;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@ExtendWith(SpringExtension.class)
@WebMvcTest(IndexController.class)
class IndexControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private DealsServiceAsync mockDealsService;
    @MockBean
    private OrdersServiceAsync mockOrdersService;

    @Test
    void testIndex() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        final Single<List<Deal>> listSingle = Single.just(List.of(deal));
        when(mockDealsService.getDeals()).thenReturn(listSingle);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(new DateTime(2020, 1, 1, 1, 0, 0, 0));
        final Product product = new Product();
        product.setId("id");
        product.setName("name");
        product.setPrice(new BigDecimal("0.00"));
        order.setProducts(List.of(product));
        final Single<List<Order>> listSingle1 = Single.just(List.of(order));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listSingle1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_DealsServiceAsyncReturnsNoItem() throws Exception {
        // Setup
        when(mockDealsService.getDeals()).thenReturn(Single.never());

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(new DateTime(2020, 1, 1, 1, 0, 0, 0));
        final Product product = new Product();
        product.setId("id");
        product.setName("name");
        product.setPrice(new BigDecimal("0.00"));
        order.setProducts(List.of(product));
        final Single<List<Order>> listSingle = Single.just(List.of(order));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listSingle);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_DealsServiceAsyncReturnsNoItems() throws Exception {
        // Setup
        when(mockDealsService.getDeals()).thenReturn(Single.just(Collections.emptyList()));

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(new DateTime(2020, 1, 1, 1, 0, 0, 0));
        final Product product = new Product();
        product.setId("id");
        product.setName("name");
        product.setPrice(new BigDecimal("0.00"));
        order.setProducts(List.of(product));
        final Single<List<Order>> listSingle = Single.just(List.of(order));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listSingle);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_DealsServiceAsyncReturnsError() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final Single<List<Deal>> listSingle = Single.error(new Exception("message"));
        when(mockDealsService.getDeals()).thenReturn(listSingle);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(new DateTime(2020, 1, 1, 1, 0, 0, 0));
        final Product product = new Product();
        product.setId("id");
        product.setName("name");
        product.setPrice(new BigDecimal("0.00"));
        order.setProducts(List.of(product));
        final Single<List<Order>> listSingle1 = Single.just(List.of(order));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listSingle1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_OrdersServiceAsyncReturnsNoItem() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        final Single<List<Deal>> listSingle = Single.just(List.of(deal));
        when(mockDealsService.getDeals()).thenReturn(listSingle);

        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(Single.never());

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_OrdersServiceAsyncReturnsNoItems() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        final Single<List<Deal>> listSingle = Single.just(List.of(deal));
        when(mockDealsService.getDeals()).thenReturn(listSingle);

        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(Single.just(Collections.emptyList()));

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }

    @Test
    void testIndex_OrdersServiceAsyncReturnsError() throws Exception {
        // Setup

        // Configure DealsServiceAsync.getDeals(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        final Single<List<Deal>> listSingle = Single.just(List.of(deal));
        when(mockDealsService.getDeals()).thenReturn(listSingle);

        // Configure OrdersServiceAsync.getRecentOrders(...).
        final Single<List<Order>> listSingle1 = Single.error(new Exception("message"));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listSingle1);

        // Run the test
        final MockHttpServletResponse response = mockMvc.perform(get("/")
                .accept(MediaType.TEXT_HTML))
                .andReturn().getResponse();

        // Verify the results
        assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
        assertThat(response.getContentAsString()).isEqualTo("expectedResponse");
    }
}
              
            
Generated Test Class
<
Utils Class
The source class is a StringUtils class that contains methods for working with Java Strings. Squaretest generated a test class containing a simple test method for replaceFirst(..). The simple test method contains assertion statements that cover the following cases.
  • The primary flow.
  • The alternate flow where the regex is invalid.
    • Squaretest inferred this case by reading the @throws tag in the Javadocs.
To create new tests, the user only needs to duplicate the assertEquals(..) line (ctrl+d), then fill in the appropriate values.
                
package com.squaretest.demo6;

public class StringUtils {

    /**
     * This is copied from org.apache.commons.lang3.RegExUtils.
     * <p>Replaces the first substring of the text string that matches the given regular expression
     * with the given replacement.</p>
     *
     * @param text  text to search and replace in, may be null
     * @param regex  the regular expression to which this string is to be matched
     * @param replacement  the string to be substituted for the first match
     * @return  the text with the first replacement processed,
     *              {@code null} if null String input
     *
     * @throws  java.util.regex.PatternSyntaxException
     *              if the regular expression's syntax is invalid
     *
     */
    public static String replaceFirst(final String text, final String regex, final String replacement) {
        if (text == null || regex == null|| replacement == null ) {
            return text;
        }
        return text.replaceFirst(regex, replacement);
    }
}
                
              
Source Class
>
              
package com.squaretest.demo6;

import org.junit.jupiter.api.Test;

import java.util.regex.PatternSyntaxException;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

class StringUtilsTest {

    @SuppressWarnings("ResultOfMethodCallIgnored")
    @Test
    void testReplaceFirst() {
        assertEquals("result", StringUtils.replaceFirst("text", "regex", "replacement"));
        assertThrows(PatternSyntaxException.class, () -> StringUtils.replaceFirst("text", "regex", "replacement"));
    }
}

              
            
Generated Test Class
<
Static Creator Methods

The source class is a Uri class that represents a website Uri. The Uri is instantiated by invoking the static creator method: parse(..). This is similar to the sealed abstract class pattern used in the Android Uri class.

Squaretest generates special tests for the static creator methods. Each test method uses the static creator method to construct the source class, then invokes all of the getter methods and compares their returned values in assertEquals(..) calls.

                
package com.squaretest.demo7;

import java.util.Map;

public class Uri {
    private final String schema;
    private final String authority;
    private final String path;
    private final Map<String, String> queryParams;

    private Uri(
            final String schema,
            final String authority,
            final String path,
            final Map<String, String> queryParams) {
        this.schema = schema;
        this.authority = authority;
        this.path = path;
        this.queryParams = queryParams;
    }

    public static Uri parse(final String theUri) throws UriParseException {
        // Actual parsing code omitted.
        return new Uri("schema", "authority", "path", Map.of());
    }

    public String getSchema() {
        return schema;
    }

    public String getAuthority() {
        return authority;
    }

    public String getPath() {
        return path;
    }

    public Map<String, String> getQueryParams() {
        return queryParams;
    }
}

                
              
Source Class
>
              
package com.squaretest.demo7;

import org.junit.jupiter.api.Test;

import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

class UriTest {

    @Test
    void testParse() throws Exception {
        // Run the test
        final Uri result = Uri.parse("theUri");
        assertEquals("result", result.getSchema());
        assertEquals("result", result.getAuthority());
        assertEquals("result", result.getPath());
        assertEquals(Map.ofEntries(Map.entry("value", "value")), result.getQueryPairs());
    }

    @Test
    void testParse_ThrowsUriParseException() {
        // Setup

        // Run the test
        assertThrows(UriParseException.class, () -> Uri.parse("theUrl"));
    }
}
              
            
Generated Test Class
<
Enum

The source class is the JavaVersion enum copied from Apache Commons Lang 3. It provides APIs for determining the version of the current JVM and comparing it to other Java versions.

Squaretest generates tests for each instance method in the enum. Each test invokes the source method on each value in the enum and compares the result to an expected value. Squaretest also generates tests for the static methods in the enum.

                
/*
 * This is copied from org.apache.commons.lang3.JavaVersion in Apache Commons Lang 3.12.
 * See https://commons.apache.org/proper/commons-lang/.
 */
package com.squaretest.demo19;

import org.apache.commons.lang3.math.NumberUtils;

/**
 * <p>An enum representing all the versions of the Java specification.
 * This is intended to mirror available values from the
 * <em>java.specification.version</em> System property. </p>
 *
 * @since 3.0
 */
public enum JavaVersion {

    /**
     * The Java version reported by Android. This is not an official Java version number.
     */
    JAVA_0_9(1.5f, "0.9"),

    /**
     * Java 1.1.
     */
    JAVA_1_1(1.1f, "1.1"),

    /**
     * Java 1.2.
     */
    JAVA_1_2(1.2f, "1.2"),

    /**
     * Java 1.3.
     */
    JAVA_1_3(1.3f, "1.3"),

    /**
     * Java 1.4.
     */
    JAVA_1_4(1.4f, "1.4"),

    /**
     * Java 1.5.
     */
    JAVA_1_5(1.5f, "1.5"),

    /**
     * Java 1.6.
     */
    JAVA_1_6(1.6f, "1.6"),

    /**
     * Java 1.7.
     */
    JAVA_1_7(1.7f, "1.7"),

    /**
     * Java 1.8.
     */
    JAVA_1_8(1.8f, "1.8"),

    /**
     * Java 1.9.
     *
     * @deprecated As of release 3.5, replaced by {@link #JAVA_9}
     */
    @Deprecated
    JAVA_1_9(9.0f, "9"),

    /**
     * Java 9.
     *
     * @since 3.5
     */
    JAVA_9(9.0f, "9"),

    /**
     * Java 10.
     *
     * @since 3.7
     */
    JAVA_10(10.0f, "10"),

    /**
     * Java 11.
     *
     * @since 3.8
     */
    JAVA_11(11.0f, "11"),

    /**
     * Java 12.
     *
     * @since 3.9
     */
    JAVA_12(12.0f, "12"),

    /**
     * Java 13.
     *
     * @since 3.9
     */
    JAVA_13(13.0f, "13"),

    /**
     * Java 14.
     *
     * @since 3.11
     */
    JAVA_14(14.0f, "14"),

    /**
     * Java 15.
     *
     * @since 3.11
     */
    JAVA_15(15.0f, "15"),

    /**
     * Java 16.
     *
     * @since 3.11
     */
    JAVA_16(16.0f, "16"),

    /**
     * Java 17.
     *
     * @since 3.12.0
     */
    JAVA_17(17.0f, "17"),

    /**
     * The most recent java version. Mainly introduced to avoid to break when a new version of Java is used.
     */
    JAVA_RECENT(maxVersion(), Float.toString(maxVersion()));

    /**
     * The float value.
     */
    private final float value;

    /**
     * The standard name.
     */
    private final String name;

    /**
     * Constructor.
     *
     * @param value  the float value
     * @param name  the standard name, not null
     */
    JavaVersion(final float value, final String name) {
        this.value = value;
        this.name = name;
    }

    //-----------------------------------------------------------------------
    /**
     * <p>Whether this version of Java is at least the version of Java passed in.</p>
     *
     * <p>For example:<br>
     *  {@code myVersion.atLeast(JavaVersion.JAVA_1_4)}<p>
     *
     * @param requiredVersion  the version to check against, not null
     * @return true if this version is equal to or greater than the specified version
     */
    public boolean atLeast(final JavaVersion requiredVersion) {
        return this.value >= requiredVersion.value;
    }

    //-----------------------------------------------------------------------
    /**
     * <p>Whether this version of Java is at most the version of Java passed in.</p>
     *
     * <p>For example:<br>
     *  {@code myVersion.atMost(JavaVersion.JAVA_1_4)}<p>
     *
     * @param requiredVersion  the version to check against, not null
     * @return true if this version is equal to or greater than the specified version
     * @since 3.9
     */
    public boolean atMost(final JavaVersion requiredVersion) {
        return this.value <= requiredVersion.value;
    }

    /**
     * Transforms the given string with a Java version number to the
     * corresponding constant of this enumeration class. This method is used
     * internally.
     *
     * @param nom the Java version as string
     * @return the corresponding enumeration constant or <b>null</b> if the
     * version is unknown
     */
    // helper for static importing
    static JavaVersion getJavaVersion(final String nom) {
        return get(nom);
    }

    /**
     * Transforms the given string with a Java version number to the
     * corresponding constant of this enumeration class. This method is used
     * internally.
     *
     * @param versionStr the Java version as string
     * @return the corresponding enumeration constant or <b>null</b> if the
     * version is unknown
     */
    static JavaVersion get(final String versionStr) {
        if (versionStr == null) {
            return null;
        }
        switch (versionStr) {
            case "0.9":
                return JAVA_0_9;
            case "1.1":
                return JAVA_1_1;
            case "1.2":
                return JAVA_1_2;
            case "1.3":
                return JAVA_1_3;
            case "1.4":
                return JAVA_1_4;
            case "1.5":
                return JAVA_1_5;
            case "1.6":
                return JAVA_1_6;
            case "1.7":
                return JAVA_1_7;
            case "1.8":
                return JAVA_1_8;
            case "9":
                return JAVA_9;
            case "10":
                return JAVA_10;
            case "11":
                return JAVA_11;
            case "12":
                return JAVA_12;
            case "13":
                return JAVA_13;
            case "14":
                return JAVA_14;
            case "15":
                return JAVA_15;
            case "16":
                return JAVA_16;
            case "17":
                return JAVA_17;
            default:
                final float v = toFloatVersion(versionStr);
                if ((v - 1.) < 1.) { // then we need to check decimals > .9
                    final int firstComma = Math.max(versionStr.indexOf('.'), versionStr.indexOf(','));
                    final int end = Math.max(versionStr.length(), versionStr.indexOf(',', firstComma));
                    if (Float.parseFloat(versionStr.substring(firstComma + 1, end)) > .9f) {
                        return JAVA_RECENT;
                    }
                } else if (v > 10) {
                    return JAVA_RECENT;
                }
                return null;
        }
    }

    //-----------------------------------------------------------------------
    /**
     * <p>The string value is overridden to return the standard name.</p>
     *
     * <p>For example, {@code "1.5"}.</p>
     *
     * @return the name, not null
     */
    @Override
    public String toString() {
        return name;
    }

    /**
     * Gets the Java Version from the system or 99.0 if the {@code java.specification.version} system property is not set.
     *
     * @return the value of {@code java.specification.version} system property or 99.0 if it is not set.
     */
    private static float maxVersion() {
        final float v = toFloatVersion(System.getProperty("java.specification.version", "99.0"));
        if (v > 0) {
            return v;
        }
        return 99f;
    }

    /**
     * Parses a float value from a String.
     *
     * @param value the String to parse.
     * @return the float value represented by the string or -1 if the given String can not be parsed.
     */
    private static float toFloatVersion(final String value) {
        final int defaultReturnValue = -1;
        if (!value.contains(".")) {
            return NumberUtils.toFloat(value, defaultReturnValue);
        }
        final String[] toParse = value.split("\\.");
        if (toParse.length >= 2) {
            return NumberUtils.toFloat(toParse[0] + '.' + toParse[1], defaultReturnValue);
        }
        return defaultReturnValue;
    }
}
                
              
Source Class
>
              
package com.squaretest.demo19;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class JavaVersionTest {

    @Test
    void testAtLeast() {
        assertTrue(JavaVersion.JAVA_0_9.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_1.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_2.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_3.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_4.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_5.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_6.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_7.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_8.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_9.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_9.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_10.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_11.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_12.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_13.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_14.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_15.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_16.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_17.atLeast(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_RECENT.atLeast(JavaVersion.JAVA_0_9));
    }

    @Test
    void testAtMost() {
        assertTrue(JavaVersion.JAVA_0_9.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_1.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_2.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_3.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_4.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_5.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_6.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_7.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_8.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_1_9.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_9.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_10.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_11.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_12.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_13.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_14.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_15.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_16.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_17.atMost(JavaVersion.JAVA_0_9));
        assertTrue(JavaVersion.JAVA_RECENT.atMost(JavaVersion.JAVA_0_9));
    }

    @Test
    void testToString() {
        assertEquals("result", JavaVersion.JAVA_0_9.toString());
        assertEquals("result", JavaVersion.JAVA_1_1.toString());
        assertEquals("result", JavaVersion.JAVA_1_2.toString());
        assertEquals("result", JavaVersion.JAVA_1_3.toString());
        assertEquals("result", JavaVersion.JAVA_1_4.toString());
        assertEquals("result", JavaVersion.JAVA_1_5.toString());
        assertEquals("result", JavaVersion.JAVA_1_6.toString());
        assertEquals("result", JavaVersion.JAVA_1_7.toString());
        assertEquals("result", JavaVersion.JAVA_1_8.toString());
        assertEquals("result", JavaVersion.JAVA_1_9.toString());
        assertEquals("result", JavaVersion.JAVA_9.toString());
        assertEquals("result", JavaVersion.JAVA_10.toString());
        assertEquals("result", JavaVersion.JAVA_11.toString());
        assertEquals("result", JavaVersion.JAVA_12.toString());
        assertEquals("result", JavaVersion.JAVA_13.toString());
        assertEquals("result", JavaVersion.JAVA_14.toString());
        assertEquals("result", JavaVersion.JAVA_15.toString());
        assertEquals("result", JavaVersion.JAVA_16.toString());
        assertEquals("result", JavaVersion.JAVA_17.toString());
        assertEquals("result", JavaVersion.JAVA_RECENT.toString());
    }

    @Test
    void testGetJavaVersion() {
        assertEquals(JavaVersion.JAVA_0_9, JavaVersion.getJavaVersion("nom"));
    }

    @Test
    void testGet() {
        assertEquals(JavaVersion.JAVA_0_9, JavaVersion.get("versionStr"));
    }
}
              
            
Generated Test Class
<

Forum

Please post questions or feedback about Squaretest below.

squaretest

Report Bugs

Track and report bugs and other issues with Squaretest on Github.

Personal License
$35
BUY
Business License
$55per seat
BUY
Personal vs Business
A personal license has your name on it; you can use it to install Squaretest on as many personal devices (devices on which you are the primary user) as you like. A company license has the company name on it as well as the number of users who may use the license. The license may be used by the given number of users; each user may use the license on as many company devices as he/she likes.

Both licenses are perpetual. They never expire.
Free Trial
You can try Squaretest for free for 30 days. Please follow the instructions here to install the plugin and begin the trial.
Purchase Justification
Developers may need to convince managers or other stakeholders that the license purchase is justified. The following argument shows how the developer time savings alone could justify the purchase.
Assumptions
  • The cost to hire a developer for 1 year is $60,000.
  • The average developer works 8 hours per day and has 3-weeks (15 business days) of paid vacation/PTO and 6 national holidays per year.
  • There are 260 weekdays per year.
  • Squaretest saves the developer 12 minutes of time each time he/she creates a new test class, on average.
  • The average developer creates one new test class every 2 weeks.
  • Squaretest saves the developer 3 minute of time each time he/she creates a new test method, on average.
  • The average developer one new test method per month.
Calculations
  • The cost of 1 developer-day is $251.05 = $60,000 / (260 - 15 - 6).
  • The cost of 1 developer-hour is $31.38 = $251.05 / 8.
  • The developer-time saved per week is 0.1125 hours = ((12 * 0.5) + (0.25 * 3)) / 60.
  • The value of the developer-time saved per week is $3.53 = 0.1125 * $31.38
  • The number of weeks required for Squaretest to pay for itself is 15.58 = $55 / $3.53
  • The number of months required for Squaretest to pay for itself is 3.895 = 15.58 / 4
  • Squaretest will pay for itself in 3.895 months.
Notes

You can download the spreadsheet with these calculations here and adjust the assumptions to match your company and project.

Frequently Asked Questions

Which version of the Velocity Engine does Squaretest use to create the tests?
Squaretest uses a fork of version 2.0 of the Apache Velocity Engine.
Can Squaretest create unit tests in Groovy?
Yes, Squaretest can create unit tests for your Java classes in Groovy. It cannot create unit tests for Groovy classes at this time, though.
Does Squaretest collect usage metrics?
There are two build variants for Squaretest. The user experience regarding usage data collection varies in each version.
Normal Squaretest Build

The normal Squaretest build is the version of Squaretest that is installed by default when you install Squaretest from the IntelliJ plugin repository.

In this build, the first time you generate a test, Squaretest will ask you to allow the anonymous collection of usage data. The data helps us identify problems with Squaretest and prioritize bug-fixes and improvements. You can enable or disable the collection of usage metrics in the Squaretest settings menu at anytime. See Usage Data for more details.
No Telemetry Build

In the No Telemetry build, the code to transmit usage data is removed from Squaretest. Users cannot enable the anonymous collection of usage data. To install this build variant, follow the instructions on Usage Data.

Does Squaretest send any data to the cloud?
Squaretest will anonymously send usage data to the cloud if the customer has allowed it as described above. Squaretest also sends requests to the licensing system; these requests include data from your license if one is present. It does not make any other network requests.

The one exception to this is if you create and use a Velocity template that makes a network request; i.e. create a Velocity template that uses code like $sourceClass.getClass().forName("java.net.URL").getConstructors() to construct an instance of java.net.URL, and then calls the openConnection() method on the URL object; using a template like that to create unit tests could cause Squaretest to make a network request.
Who stands behind Squaretest?
Squaretest LLC was founded by Nate Shevick, a 6+ year software developer. Nate worked for amazon.com for over 4 years before leaving to create Squaretest in 2017.
Is Squaretest affiliated with Square, Inc?
No. Squaretest is not affiliated with Square, Inc. in any way.
Where did the name Squaretest come from?
The Carpenter's Square is simple, easy-to-use and incredibly useful for carpentry and woodworking. Squaretest aims to be like the Carpenter's Square for writing unit tests.
Why not release Squaretest as Open Source?
Squaretest was created to help software developers avoid spending time and energy writing boilerplate code. Due to the complexity of software in general, this required a substantial development effort. Additionally, keeping Squaretest up-to-date with the latest coding conventions andtest frameworks requires sustained development effort. Supporting such a development effort requires funding.

Several open source business models were considered. Unfortunately, none of them appeared to provide enough revenue to support the development required to create and maintain Squaretest.

Terms and Conditions

The Squaretest plugin may be used in accordance with the following Terms and Conditions.

Contact us

Please use the following emails to contact us.
Buy Squaretest Personal License
The name to appear on your license
Your license will be sent to this email address.
Buy Squaretest Business License
The name to appear on the license
Your license will be sent to this email address.
Please email sales@squaretest.com to purchase a license for more than 100 users.