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 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, when appropriate
  • A test method for each public and package-local method in the source class, containing
    • Code to initialize arguments required by the method
    • Mockito stubs like when() and doAnswer() statements
    • Code to invoke the method
    • An assertEquals() call or Groovy assertion statement
    • Mockito verify() statements
    • Code to initialize data transfer objects (DTOs) used in the above
  • Test methods for alternate flows, including cases where:
    • Dependency methods throw exceptions
    • Dependency methods return either null or absent values like Optional.empty()
    • Dependency methods return empty values like Collections.emptyList()
    • Dependency methods return failure values like CompletableFuture.failedFuture(..)
    • Dependency methods return broken I/O values like new BrokenInputStream()
    • Dependency methods return empty I/O values like InputStream.nullInputStream()
    • Method parameters contain broken I/O values like new BrokenInputStream()

Choose Which Dependencies Should Be Mocked

Select Squaretest | Generate Test - Confirm Options (Alt+Insert+Generate Test - Confirm Options) to choose the following options before creating the test class:
  • Which dependencies should be mocked
  • Which methods should be tested
  • Whether to construct the source class in a setup method or in each test method.

Uses Dataflow Analysis and Control Flow Analysis

Squaretest uses dataflow analysis and control flow analysis to generate as much of the tests as it can. In many cases developers only need to fill in the details in order to complete the tests. For example change the placeholder values, add assertions, etc.

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 that 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.

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 handle the following design patterns in the source class.
  • The standard Java component with dependencies provided in the constructor
  • Components with private fields annotated with @Inject, @Autowired or similar annotations
  • Components with package-local fields annotated with @Inject or similar annotations.
  • Components with dependencies provided via setter methods
  • Classes with static factory methods like parse(..) or from(..) but no package-visible constructor; i.e. the sealed abstract class and similar patterns
  • Abstract classes in general
  • Classes containing only static methods; e.g. the Utils classes
  • Traditional Singletons
  • Enum Singletons
  • Enums in general
  • Android activities (Robolectric3 and AndroidJUnit4 templates only, limited support)
  • 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 that use the following patterns.
  • Classes with data provided via the constructor
  • Classes with data provided via lombok builder methods
  • 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 factory methods like 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 variables 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, the JUnit4 Mockito Runner or the TestNG Mockito Listener
  • Use Mockito BDD
  • Use static imports for openMocks and related methods
  • Set the maximum number of bean setter methods that will be called when initializing a data object
  • 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 variables of type List will be set to either Arrays.asList(..) or List.of(..). Squaretest recognizes 500+ default types from the JDK and various open source libraries, including.
  • The JDK 8+
  • Apache Commons Lang 2 and 3
  • Google Guava
  • RxJava
  • Retrofit
  • AWS SDK V1 and V2
  • The Spring Framework
Squaretest also selects default values based on the libraries present on the test classpath. For example dependencies and local variables of type Executor will use MoreExecutors.directExecutor() from Google Guava if it is 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 Test Methods

Add Multiple Test Methods To Your Test Class

Open the test class and select Squaretest | Generate Test Methods (Alt+Insert+Generate Test Methods) to see a list of test methods to add.

The list includes tests for the alternate flows described above. For example if a source method calls fooService.getFoo(), and getFoo() can throw an IOException, Squaretest will suggest a test method where fooService.getFoo() is configured to throw an IOException.

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
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

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 | Marketplace
  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
    • Choose Squaretest | Generate Test from the toolbar
    • Type Alt+Insert+Generate Test
  3. Follow the instructions on the Configure Squaretest Module Settings dialog.
    The options are as follows.
    • Test Language the language to create the tests in (either Java or Groovy)
    • Template the Apache Velocity template used to create the 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 the tests and any package directories required for this module.
    • Promote Test Language and Template to Project Settings whether 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 Squaretest should try to configure the settings for 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 the 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. The options are as follows.
  • Open the Test File
    • 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.
  • Manage All Templates
    • this shows a dialog enabling you to delete or rename any templates you've created.
  • Manage License
    • this shows a dialog enabling you to input or remove your Squaretest license.
  • Data Constructor Limit When Bean Option Available
    • Specifies the longest, nested constructor call (number of parameters) that will be used to initialize recognized data classes. If the constructor call exceeds this limit Squaretest will use the zero-argument constructor and bean setter methods to initialize the class, if one is available.
      Recognized Data Classes
      Squaretest considers a class to be a data class if it has at least one data annotation. Examples include annotations with canonical names that start with "lombok", "javax.xml.bind.annotation", etc.
  • Constructor Limit When Bean Option Available
    • Specifies the longest, nested constructor call (number of parameters) that will be used to initialize classes that contain a zero-argument constructor. If the constructor call exceeds this limit Squaretest will use the zero-argument constructor and bean setter methods to initialize the class. This does not apply to classes with type parameters.
  • Constructor Limit When Other Options Available
    • Specifies the longest, nested constructor call (number of parameters) that will be used to initialize classes that contain an alternative initialization method. If the constructor call exceeds this limit Squaretest will use the alternative initialization method to construct the class. This does not apply to classes with type parameters.
  • Final Constructor Limit
    • Specifies the longest, nested constructor call (number of parameters) that will be used to initialize classes. If the constructor call exceeds this limit Squaretest will initialize the class to either null or a similar default value.
  • Max Number of Builder Methods to Call
    • Specifies the maximum number of builder methods that will be called when initializing a class. Squaretest will recursively invoke builder methods for properties set or accessed in the source class and related classes. This setting limits the number that will be called.
  • Enable Completion Suggestions for Test Methods
    • Specifies whether Squaretest should show completion suggestions for test methods when typing in a test class.
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, the test sources root contains source files matching the template language and framework in the Project Settings, and the test sources root's classpath does not contain newer versions of the test framework (e.g. the project framework is JUnit4 and the test sources root has JUnit5 on the classpath). This is the most common scenario.
      • The module contains no test sources roots and its dependent modules collectively contains exactly one test sources root that matches the criteria described above.
    • 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 Shortcuts
The Squaretest keyboard shortcuts 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 four parts. Most developers will only need to modify the first two 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 between sections of the test class. These are removed in the code cleanup.
  • Don't worry about over-indenting the Java code or Groovy code in the 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 %APPDATA%\JetBrains\<<IntelliJVersion>>\fileTemplates
Mac OS X ~/Library/Application Support/JetBrains/<<IntelliJVersion>>/fileTemplates
Linux ~/.config/JetBrains/<<IntelliJVersion>>/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 variables 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 variables 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, the JUnit4 Mockito Runner, or the TestNG Mockito Listener. By default, this is set to true if the extension, runner or listener is on the test classpath.
$shouldUseMockitoBdd boolean Determines whether the template will use Mockito BDD .
$minNumberOfSettersToCall int Sets the minimum number of setters to call when initializing a top-level bean.
$maxNumberOfSettersToCall int Sets the maximum number of setters to call when initializing a top-level bean.
$useStaticImportForInitMocks boolean This specifies whether MockitoAnnotations.openMocks 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, String>

or

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 either a String or a Map. The String value only needs to contain the initialization expression. Maps must contain 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 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 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 Options" action.
$isCreatingNewTest boolean Indicates whether the template is being invoked to create a new test class or to add test methods to an existing one.
$springWebMvcTestIncludesSpringExtension boolean Indicates whether the Spring @WebMvcTest annotation includes the SpringExtension automatically.
$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 3StringUtils, plus a few extra methods.
$TestInfo TestInfoFactory The TestInfoFactory class provides methods for creating TestInfo objects that describe test cases that should be rendered.
$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.
$AltInfo AltInfoFactory This class is deprecated. Please use TestInfoFactory.
Macro Variables
Macro variables are set by the #initializeTemplateDataModel() macro. The #initializeTemplateDataModel() macro is defined at the bottom of the Squaretest templates and is invoked after the Quick Settings section. This macro sets variables used in the test class rendering logic. Those 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.
$hasReflectionTestUtils boolean boolean indicating whether Spring ReflectionTestUtils is on the test classpath.
$initMocksMethodName String Contains "openMocks" if $hasOpenMocksMethod is true; otherwise, this contains "initMocks".
$mockMembers FluentList<Variable> A subset of $dependencies containing all fields that should be mocked and stored in members in the test class.
$methodsToTest FluentList<Method> A FluentList<Method> containing the methods that should be tested.
$shouldRenderMockitoCloseable boolean boolean indicating whether a mockitoCloseable test class member should be rendered.
$shouldRenderSetupMethod boolean boolean indicating whether a setup method should be rendered.
$shouldRenderTearDownMethod boolean boolean indicating whether a tearDown method should be rendered.
$shouldRenderSourceClassMember boolean boolean indicating whether an instance of the source class should be created and stored in a member of the test class.
$shouldUseInjectMocks boolean a boolean indicating whether @InjectMocks should be used to provide dependencies to the instance of the $sourceClass.
Macro Variables Used In Source Class Initialization
Name Type Description
$fieldsThatCannotBeSet
boolean Source class members that Squaretest does not know how to set.
$fieldsToSetWithReflection
boolean Source class members that should be set via reflection to initialize the source class.
$packageLocalFieldsToSet
boolean The package local fields that should be set to initialize the source class.
$packageLocalFieldsWithInlineMocks
boolean subset of $packageLocalFieldsToSet that contains package local fields that are set to inline mocks.
$setterMethodsToCall
boolean The setter methods that should be used to initialize the source class.
$shouldCreateSourceClassInEachTestMethod
boolean boolean indicating whether the source class should be constructed in each test method as opposed to the setup(..) method.
$sourceClassConstructor
boolean The constructor that should be used to construct the source class.
Macro Variables in Spring Templates
The #initializeTemplateDataModel() macro sets the following additional variables in Spring templates.

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.
$shouldRenderMockMvc
boolean boolean indicating whether a Spring MockMvc test class member should be rendered.
$shouldUseSpringExtension
boolean boolean indicating whether the JUnit 5 SpringExtension should be used.
$shouldUseSpringWebMvcTest
boolean boolean indicating whether the @WebMvcTest annotation should be used.
$springController
boolean This is true if the $sourceClass is a Spring controller.
Macro Variables Set Based on Mockito BDD Setting
The #initializeTemplateDataModel() macro sets the following variables based on the $shouldUseMockitoBdd Quick Setting.

Name Type Description
$doAnswer
String Contains either 'doAnswer' or 'willAnswer'
$doReturn
String Contains either 'doReturn' or 'willReturn'
$doThrow
String Contains either 'doThrow' or 'willThrow'
$thenReturn
String Contains either 'thenReturn' or 'willReturn'
$thenThrow
String Contains either 'thenThrow' or 'willThrow'
$when
String Contains either 'when' or 'given'
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 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 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 this class has an annotation that starts with one of the provided prefixes.
hasAnnotationWithPrefix(
String... prefixes)
boolean Returns whether 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.
containingClass SourceClass Returns the class that contains this method. For Api.DependencyInteraction methods, this returns null.
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.
getter boolean True if the method is a getter.
getterOrSetter boolean True if the method is a getter or a setter.
getSuperMethodParametersAtIndex(
int index)
FluentList<Variable> Returns all super method parameters at the specified index.
hasAnnotation(
List<String> annotationNames)
boolean Returns whether 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 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 this method has an annotation that starts with one of the provided prefixes.
hasAnnotationWithPrefix(
String... prefixes)
boolean Returns whether 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.
inMainSourceClass boolean True if the method is in the main Source Class (the class the test is being created for).
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().
setter boolean True if this method is a setter.
shouldTest boolean Mutable property indicating whether this method should be tested.
shouldUseSimpleTest boolean Whether the template should render a simple, 1-line test method for this source method.
simpleGetter boolean This is deprecated. Please Use the getter property.
simpleGetterOrSetter boolean This is deprecated. Please use the getterOrSetter property.
simpleSetter boolean This is deprecated. Please use the setter property.
static boolean True if the method is static.
superMethods FluentList<Method> Contains all super methods this method overrides.
targetField ClassMember Returns the target field this method is a getter or setter for, or null if this is not a getter or setter or if the target field could not be determined.
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.
containingMethod Method The method that contains this parameter or null if this is a ClassMember.
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 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 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 this Variable has an annotation that starts with one of the provided prefixes.
hasAnnotationWithPrefix(
String... prefixes)
boolean Returns whether this Variable has an annotation that starts with one of the provided prefixes.
initExpression String Alias for type.initExpression.
member boolean True if this Variable is a ClassMember.
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.
getters FluentList<Method> Getter methods for this ClassMember
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
setters FluentList<Method> Setter methods for this ClassMember
static boolean True if the member is static.
transient boolean True if the member is declared to be transient.
visibleToTestClass boolean True if the member is visible to the test class.
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 this type should be spied; i.e. Mockito.spy(..).
shouldStoreInReference boolean A boolean indicating whether 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".
TestInfo
Name Type Description
method Method The source method this test case should cover.
expectedValueAbsent boolean True if the source method is expected to return an absent value; e.g. Optional.empty().
expectedValueNull boolean True if the source method is expected to return null.
expectedValueTrue boolean True if the source method is expected to return true.
expectedException Exception The exception the source method is expected to throw.
mockedDIs FluentList<DI> The mocked dependency interactions used in this test case.
paramWithEmptyIo Variable Mutable property containing the source method parameter that should contain an empty I/O value in this test case.
paramWithBrokenIo Variable Mutable property containing the source method parameter that should contain a broken I/O value in this test case.
subjectDi DependencyInteraction The dependency interaction that is the subject of this test.
subjectDiReturnsEmpty boolean True if the subject DependencyInteraction should return an empty value.
subjectDiReturnsAbsent boolean True if the subject DependencyInteraction should return an absent value.
subjectDiReturnsEmptyIo boolean True if the subject DependencyInteraction should return an empty I/O Value.
subjectDiReturnsBrokenIo boolean True if the subject DependencyInteraction should return a broken I/O Value.
subjectDiReturnsFailure boolean True if the subject DependencyInteraction should return a failure value.
subjectDiExceptionToThrow Exception The exception the subject DependencyInteraction should throw in this test case.
shouldReturnAbsent(
  DependencyInteraction di)
boolean Returns true if the provided DependencyInteraction should return an absent value.
shouldReturnEmpty(
  DependencyInteraction di)
boolean Returns true if the provided DependencyInteraction should return an empty value.
shouldReturnEmptyIo(
  DependencyInteraction di)
boolean Returns true if the provided DependencyInteraction should return an empty I/O value.
shouldReturnBrokenIo(
  DependencyInteraction di)
boolean Returns true if the provided DependencyInteraction should return a broken I/O value.
shouldThrowException(
  DependencyInteraction di)
boolean Returns true if the provided DependencyInteraction should throw an exception in this test case.
getExceptionToThrow(
  DependencyInteraction di)
Exception Returns the Exception the provided DependencyInteraction should throw in this test case.
shouldReturnFailure(
  DependencyInteraction di)
boolean Returns true if the provided DependencyInteraction should return a failure value in this test case.
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.
last T Returns the last item in the list or null if the list is empty.
concat(
  Collection<T> listToAppend)
FluentList<T> Returns a new list containing the items from this list followed by the items from listToAppend.
containsAny(
  List<?> searchItems)
boolean Returns whether this list contains any of the provided searchItems.
containsAnyWith(
  String attrNameExp,
  Object... searchValues)
boolean Returns whether the list contains an item with property: attrNameExp and a value in the searchValues.
containsAnyWithAnnotation(
  List<String> annotations)
boolean Returns whether the list contains any items with at least one of the provided annotations.
containsAnyWithAnnotation(
  String... annotations)
boolean Returns whether the list contains any items with at least one of the provided annotations.
containsAnyWithAnnotationPrefix(
  List<String> annotations)
boolean Returns whether the list contains any items with at least one annotation that starts with one of the given prefixes.
containsAnyWithAnnotationPrefix(
  String... prefixes)
boolean Returns whether the list contains any items with at least one annotation that starts with one of the given prefixes.
containsAnyWithNonNull(
  String attrNameExp)
boolean Returns whether the list contains an item with property: attrNameExp and a value that is not null.
containsAnyWithPrefix(
  String attrNameExp,
  List<String>)
boolean Returns whether 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 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 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)".
filter2(
  String attrNameExp,
  List<?> searchValues)
FluentList<T> This returns a new list containing items in the list that have a property with name: attrNameExp and a value in searchValues.
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)"
filterOut2(
  String attrNameExp,
  List<?> searchValues)
FluentList<T> Returns a list excluding items with property: attrNameExp and a value in searchValues.
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.
join(delimiter) String Returns a String containing each element of this list joined with the provided delimiter.
limit(num) FluentList<T> Returns a new FluentList with the first num elements of this 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.
updateMemberFieldNameWithClassScope(
  Variable variable)
void
Updates the testClassMemberName property of the provided variable in a way that avoids name collisions with other variables or types passed to this method during test generation.
ClassUtils
Method Return Type Description
hasBeanWithUsedProperty(
  Type type)
boolean
Returns whether this type has a bean with at least one used property in its Type.initExpressionBeans list.
isInTestClasspath(
  String canonicalName)
boolean
Returns whether 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.
askUserToConfirmSettingsV2(
  Map<String, Object> settings)
Map<String, Object> Shows a dialog asking the user to confirm the provided settings.
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.
TestInfoFactory
Method Return Type Description
fromDiThatThrows(
  sourceMethod,
  mockedDIs, di,
  diExceptionToThrow)
TestInfo Returns an TestInfo object with the provided source method, mocked dependency interactions, dependency interaction that should throw an exception and the exception that should be thrown.
fromDiToReturnAbsent(
  sourceMethod,
  mockedDIs, di)
TestInfo Returns an TestInfo object with the provided sourceMethod, mocked dependency interactions and the dependency interaction that should return null or an absent value for the test case.
fromDiToReturnBrokenIo(
  sourceMethod,
  mockedDIs, di)
TestInfo Returns an TestInfo object with the provided sourceMethod, mocked dependency interactions and the dependency interaction that should return a broken I/O value for the test case.
fromDiToReturnEmpty(
  sourceMethod,
  mockedDIs, di)
TestInfo Returns an TestInfo object with the provided sourceMethod, mocked dependency interactions and the dependency interaction that should return an empty value for the test case.
fromDiToReturnEmptyIo(
  sourceMethod,
  mockedDIs, di)
TestInfo Returns an TestInfo object with the provided sourceMethod, mocked dependency interactions and the dependency interaction that should return an empty I/O value for the test case.
fromDiToReturnFailure(
  sourceMethod,
  mockedDIs, di)
TestInfo Returns an TestInfo object with the provided sourceMethod, mocked dependency interactions and the dependency interaction that should return a failure value for the test case.
fromExpectedException(
  sourceMethod, mockedDIs,
  expectedException)
TestInfo Returns a TestInfo object with the provided source method, mocked dependency interactions and expectedException.
fromParamWithBrokenIo(
  sourceMethod,
  mockedDIs, param)
TestInfo Returns a TestInfo object with the provided sourceMethod, mocked dependency interactions and parameter that should contain a broken I/O value for the test case.
fromParamWithEmptyIo(
  sourceMethod,
  mockedDIs, param)
TestInfo Returns a TestInfo object with the provided sourceMethod, mocked dependency interactions and parameter that should contain an empty I/O value for the test case.
newValue()
TestInfo Returns an empty TestInfo object.
primaryFlow(
  sourceMethod,
  mockedDIs)
TestInfo Returns a TestInfo representing the primary flow test case for the provided source method and mocked dependency interactions.
updateDependencies(
  FluentList<Variable>
  dependencies)
TestInfo Updates the dependencies used to create test cases.
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 enables developers 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 enables developers 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 enables developers 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;
import java.util.stream.Collectors;

public class DealsServiceAdapter {

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

    private final DealsServiceClient dealsService;
    private final MetricsAdapter metricsAdapter;

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

    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 e) {
            Log.log(Level.WARNING, "Exception querying deals service.", e);
            metricsAdapter.recordServiceException(userId, e);
            return Collections.emptyList();
        } catch (final NetworkException e) {
            Log.log(Level.WARNING, "Exception querying deals service.", e);
            metricsAdapter.recordNetworkException(userId, e);
            return Collections.emptyList();
        }
    }

    private List<DisplayDeal> convertToDisplayDeals(final List<Deal> deals) {
        return deals.stream().map(deal -> new DisplayDeal(deal.getId(), deal.getProductName(),
                deal.getPrice(), deal.getImageUrl())).collect(Collectors.toList());
    }
}
                  
                
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.util.Collections;
import java.util.List;

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

@ExtendWith(MockitoExtension.class)
class DealsServiceAdapterTest {

    @Mock
    private DealsServiceClient mockDealsService;
    @Mock
    private MetricsAdapter mockMetricsAdapter;

    private DealsServiceAdapter dealsServiceAdapterUnderTest;

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

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

        // 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.setImageUrl("imageUri");
        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
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenThrow(ServiceException.class);

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

        // Verify the results
        assertEquals(Collections.emptyList(), result);
        verify(mockMetricsAdapter).recordServiceException(eq("userId"), any(ServiceException.class));
    }

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

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

        // Verify the results
        assertEquals(Collections.emptyList(), result);
        verify(mockMetricsAdapter).recordNetworkException(eq("userId"), any(NetworkException.class));
    }
}
                
              
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;
import java.util.stream.Collectors;

public class DealsServiceAdapter {

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

    private final DealsServiceClient dealsService;
    private final MetricsAdapter metricsAdapter;

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

    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 e) {
            Log.log(Level.WARNING, "Exception querying deals service.", e);
            metricsAdapter.recordServiceException(userId, e);
            return Collections.emptyList();
        } catch (final NetworkException e) {
            Log.log(Level.WARNING, "Exception querying deals service.", e);
            metricsAdapter.recordNetworkException(userId, e);
            return Collections.emptyList();
        }
    }

    private List<DisplayDeal> convertToDisplayDeals(final List<Deal> deals) {
        return deals.stream().map(deal -> new DisplayDeal(deal.getId(), deal.getProductName(),
                deal.getPrice(), deal.getImageUrl())).collect(Collectors.toList());
    }
}
                
              
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.util.Collections;
import java.util.List;

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

@ExtendWith(MockitoExtension.class)
class DealsServiceAdapterTest {

    @Mock
    private DealsServiceClient mockDealsService;
    @Mock
    private MetricsAdapter mockMetricsAdapter;

    private DealsServiceAdapter dealsServiceAdapterUnderTest;

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

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

        // 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.setImageUrl("imageUri");
        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
        when(mockDealsService.getDeals(any(GetDealsRequest.class))).thenThrow(ServiceException.class);

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

        // Verify the results
        assertEquals(Collections.emptyList(), result);
        verify(mockMetricsAdapter).recordServiceException(eq("userId"), any(ServiceException.class));
    }

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

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

        // Verify the results
        assertEquals(Collections.emptyList(), result);
        verify(mockMetricsAdapter).recordNetworkException(eq("userId"), any(NetworkException.class));
    }
}
              
            
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.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;
import java.util.stream.Collectors;

public class DealsServiceAdapterAsync {

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

    private final DealsServiceClient dealsService;
    private final ExecutorService executorService;
    private final MetricsAdapter metricsAdapter;

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

    public CompletableFuture<List<DisplayDeal>> getDeals(final String userId) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return getDealsInternal(userId);
            } catch (final ServiceException e) {
                Log.log(Level.WARNING, "Exception querying deals service.", e);
                metricsAdapter.recordServiceException(userId, e);
                throw new CompletionException(e);
            } catch (final NetworkException e) {
                Log.log(Level.WARNING, "Exception querying deals service.", e);
                metricsAdapter.recordNetworkException(userId, 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) {
        return deals.stream().map(deal -> new DisplayDeal(deal.getId(), deal.getProductName(),
                deal.getPrice(), deal.getImageUrl())).collect(Collectors.toList());
    }
}
                  
                
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.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class DealsServiceAdapterAsyncTest {

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

    private DealsServiceAdapterAsync dealsServiceAdapterAsyncUnderTest;

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

    @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.setImageUrl("imageUri");
        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));
        verify(mockMetricsAdapter).recordServiceException(eq("userId"), any(ServiceException.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));
        verify(mockMetricsAdapter).recordNetworkException(eq("userId"), any(NetworkException.class));
    }
}
                
              
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)) {
            final PDDocument purchaseOrderDoc = PDDocument.load(s3Object.getObjectContent());
            metricAdapter.recordPurchaseOrderDocumentDownloaded(orderId);
            return purchaseOrderDoc;
        } catch (final AmazonServiceException e) {
            metricAdapter.recordServiceException(orderId, e);
            throw new PurchaseOrderStoreException(
                    String.format("AmazonServiceException while downloading object with path: %s", path), e);
        } catch (final SdkClientException e) {
            metricAdapter.recordClientException(orderId, e);
            throw new PurchaseOrderStoreException(
                    String.format("SdkClientException while downloading object with path: %s", path), e);
        } catch (final IOException e) {
            metricAdapter.recordIOException(orderId, e);
            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.IOException;
import java.io.InputStream;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
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).recordPurchaseOrderDocumentDownloaded("orderId");
    }

    @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).recordPurchaseOrderDocumentDownloaded("orderId");
    }

    @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).recordIOException(eq("orderId"), any(IOException.class));
    }

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

        // Run the test
        assertThrows(PurchaseOrderStoreException.class, () -> purchaseOrderStoreUnderTest.getPurchaseOrder("orderId"));
        verify(mockMetricAdapter).recordClientException(eq("orderId"), any(SdkClientException.class));
    }

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

        // Run the test
        assertThrows(PurchaseOrderStoreException.class, () -> purchaseOrderStoreUnderTest.getPurchaseOrder("orderId"));
        verify(mockMetricAdapter).recordServiceException(eq("orderId"), any(AmazonServiceException.class));
    }
}
                
              
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.recordPurchaseOrderDocumentDownloaded(orderId);
            return purchaseOrderDoc;
        } catch (final NoSuchKeyException e) {
            metricAdapter.recordPurchaseOrderNotFound(orderId, e);
            throw new PurchaseOrderStoreException(String.format("S3Object with path: %s not found", path), e);
        } catch (final S3Exception e) {
            metricAdapter.recordServiceException(orderId, e);
            throw new PurchaseOrderStoreException(
                    String.format("S3Exception while downloading object with path: %s", path), e);
        } catch (final SdkClientException e) {
            metricAdapter.recordClientException(orderId, e);
            throw new PurchaseOrderStoreException(
                    String.format("SdkClientException while downloading object with path: %s", path), e);
        } catch (final IOException e) {
            metricAdapter.recordIOException(orderId, e);
            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.*;

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

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
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).recordPurchaseOrderDocumentDownloaded("orderId");
    }

    @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).recordPurchaseOrderDocumentDownloaded("orderId");
    }

    @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).recordIOException(eq("orderId"), any(IOException.class));
    }

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

        // Run the test
        assertThrows(PurchaseOrderStoreException.class, () -> purchaseOrderStoreUnderTest.getPurchaseOrder("orderId"));
        verify(mockMetricAdapter).recordPurchaseOrderNotFound(eq("orderId"), any(NoSuchKeyException.class));
    }

    @Test
    void testGetPurchaseOrder_S3ClientThrowsInvalidObjectStateException() {
        // Setup
        when(mockS3Client.getObject(GetObjectRequest.builder()
                .bucket("bucketName")
                .key("key")
                .build())).thenThrow(InvalidObjectStateException.class);

        // Run the test
        assertThrows(PurchaseOrderStoreException.class, () -> purchaseOrderStoreUnderTest.getPurchaseOrder("orderId"));
        verify(mockMetricAdapter).recordServiceException(eq("orderId"), any(S3Exception.class));
    }

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

        // Run the test
        assertThrows(AwsServiceException.class, () -> purchaseOrderStoreUnderTest.getPurchaseOrder("orderId"));
    }

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

        // Run the test
        assertThrows(PurchaseOrderStoreException.class, () -> purchaseOrderStoreUnderTest.getPurchaseOrder("orderId"));
        verify(mockMetricAdapter).recordClientException(eq("orderId"), any(SdkClientException.class));
    }

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

        // Run the test
        assertThrows(PurchaseOrderStoreException.class, () -> purchaseOrderStoreUnderTest.getPurchaseOrder("orderId"));
        verify(mockMetricAdapter).recordServiceException(eq("orderId"), any(S3Exception.class));
    }
}
                
              
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;
    private final MetricsAdapter metricsAdapter;

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

    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) {
            metricsAdapter.recordOrderStoreException(orderId, e);
            throw new OrderStoreException(e);
        }

        // Validate the order.
        if (order == null) {
            metricsAdapter.recordOrderNotFound(orderId);
            throw new OrderNotFoundException(orderId);
        }
        metricsAdapter.recordOrderFound(orderId);
        return order;
    }
}
                  
                
Source Class
>
                
package com.squaretest.demo11;

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException;
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.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class OrderStoreTest {

    @Mock
    private DynamoDBMapper mockDynamoDBMapper;
    @Mock
    private MetricsAdapter mockMetricsAdapter;

    private OrderStore orderStoreUnderTest;

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

    @Test
    void testGetOrder() throws Exception {
        // Setup
        // Configure DynamoDBMapper.load(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(LocalDateTime.of(2020, 1, 1, 0, 0, 0, 0).toInstant(ZoneOffset.UTC));
        final Product product = new Product();
        product.setId("id");
        order.setProducts(List.of(product));
        when(mockDynamoDBMapper.load(Order.class, "orderId")).thenReturn(order);

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

        // Verify the results
        verify(mockMetricsAdapter).recordOrderFound("orderId");
    }

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

        // Run the test
        assertThrows(OrderNotFoundException.class, () -> orderStoreUnderTest.getOrder("orderId"));
        verify(mockMetricsAdapter).recordOrderNotFound("orderId");
    }

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

        // Run the test
        assertThrows(OrderStoreException.class, () -> orderStoreUnderTest.getOrder("orderId"));
        verify(mockMetricsAdapter).recordOrderStoreException(eq("orderId"), any(Exception.class));
    }
}
                
              
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;
    private final MetricsAdapter metricsAdapter;

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

    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) {
            metricsAdapter.recordOrderStoreException(e);
            throw new OrderStoreException(e);
        }

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

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.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;

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

@ExtendWith(MockitoExtension.class)
class OrderStoreTest {

    @Mock
    private DynamoDbTable<Order> mockOrdersTable;
    @Mock
    private MetricsAdapter mockMetricsAdapter;

    private OrderStore orderStoreUnderTest;

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

    @Test
    void testGetOrder() throws Exception {
        // Setup
        // Configure DynamoDbTable.getItem(...).
        final Order order = new Order();
        order.setId("id");
        order.setShipAddress("shipAddress");
        order.setShipDate(LocalDateTime.of(2020, 1, 1, 0, 0, 0, 0).toInstant(ZoneOffset.UTC));
        final Product product = new Product();
        product.setId("id");
        order.setProducts(List.of(product));
        when(mockOrdersTable.getItem(Key.builder()
                .partitionValue("orderId")
                .build())).thenReturn(order);

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

        // Verify the results
        verify(mockMetricsAdapter).recordOrderRetrieved("orderId");
    }

    @Test
    void testGetOrder_DynamoDbTableReturnsNull() {
        // Setup
        when(mockOrdersTable.getItem(Key.builder()
                .partitionValue("orderId")
                .build())).thenReturn(null);

        // Run the test
        assertThrows(OrderStoreException.class, () -> orderStoreUnderTest.getOrder("orderId"));
        verify(mockMetricsAdapter).recordOrderNotFound("orderId");
    }

    @Test
    void testGetOrder_DynamoDbTableThrowsSdkClientException() {
        // Setup
        when(mockOrdersTable.getItem(Key.builder()
                .partitionValue("orderId")
                .build())).thenThrow(SdkClientException.class);

        // Run the test
        assertThrows(OrderStoreException.class, () -> orderStoreUnderTest.getOrder("orderId"));
        verify(mockMetricsAdapter).recordOrderStoreException(any(Exception.class));
    }

    @Test
    void testGetOrder_DynamoDbTableThrowsDynamoDbException() {
        // Setup
        when(mockOrdersTable.getItem(Key.builder()
                .partitionValue("orderId")
                .build())).thenThrow(DynamoDbException.class);

        // Run the test
        assertThrows(OrderStoreException.class, () -> orderStoreUnderTest.getOrder("orderId"));
        verify(mockMetricsAdapter).recordOrderStoreException(any(Exception.class));
    }
}
                
              
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.junit.jupiter.api.Assertions.assertThrows;
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()
                        .text("text")
                        .build())
                .build();
        when(mockComService.detectEntities(DetectEntitiesRequest.builder()
                .text("text")
                .languageCode(LanguageCode.EN)
                .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() {
        // Setup
        when(mockComService.detectEntities(DetectEntitiesRequest.builder()
                .text("text")
                .languageCode(LanguageCode.EN)
                .build())).thenThrow(InvalidRequestException.class);

        // Run the test
        assertThrows(LanguageServiceException.class, () -> languageAnalyzerUnderTest.getEntitiesMentioned("text"));
    }

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

        // Run the test
        assertThrows(LanguageServiceException.class, () -> languageAnalyzerUnderTest.getEntitiesMentioned("text"));
    }

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

        // Run the test
        assertThrows(LanguageServiceException.class, () -> languageAnalyzerUnderTest.getEntitiesMentioned("text"));
    }

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

        // Run the test
        assertThrows(LanguageServiceException.class, () -> languageAnalyzerUnderTest.getEntitiesMentioned("text"));
    }

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

        // Run the test
        assertThrows(LanguageServiceException.class, () -> languageAnalyzerUnderTest.getEntitiesMentioned("text"));
    }

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

        // Run the test
        assertThrows(LanguageServiceException.class, () -> languageAnalyzerUnderTest.getEntitiesMentioned("text"));
    }

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

        // Run the test
        assertThrows(LanguageServiceException.class, () -> languageAnalyzerUnderTest.getEntitiesMentioned("text"));
    }

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

        // Run the test
        assertThrows(LanguageServiceException.class, () -> languageAnalyzerUnderTest.getEntitiesMentioned("text"));
    }
}
                
              
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.recordPurchaseOrderRetrieved(orderId);
            return purchaseOrderDoc;
        } catch (final StorageException e) {
            metricAdapter.recordStorageException(orderId, e);
            throw new PurchaseOrderStoreException(
                    String.format("StorageException while downloading object with path: %s", path), e);
        } catch (final IOException e) {
            metricAdapter.recordIOException(orderId, e);
            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.junit.jupiter.api.Assertions.assertThrows;
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("bucketName", "blob")).thenReturn("content".getBytes());

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

        // Verify the results
        verify(mockMetricAdapter).recordPurchaseOrderRetrieved("orderId");
    }

    @Test
    void testGetPurchaseOrder_StorageThrowsStorageException() {
        // Setup
        when(mockStorage.readAllBytes("bucketName", "blob")).thenThrow(StorageException.class);

        // Run the test
        assertThrows(PurchaseOrderStoreException.class, () -> purchaseOrderStoreUnderTest.getPurchaseOrder("orderId"));
        verify(mockMetricAdapter).recordStorageException("orderId",
                  new StorageException(0, "message", "reason", new Exception("message")));
    }
}
                
              
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.junit.jupiter.api.Assertions.assertThrows;
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("name")
                        .build())
                .build();
        when(mockLanguageService.analyzeEntities(AnalyzeEntitiesRequest.newBuilder()
                .setDocument(Document.newBuilder()
                        .setType(Document.Type.PLAIN_TEXT)
                        .setContent("value")
                        .build())
                .setEncodingType(EncodingType.UTF16)
                .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() {
        // Setup
        when(mockLanguageService.analyzeEntities(AnalyzeEntitiesRequest.newBuilder()
                .setDocument(Document.newBuilder()
                        .setType(Document.Type.PLAIN_TEXT)
                        .setContent("value")
                        .build())
                .setEncodingType(EncodingType.UTF16)
                .build())).thenThrow(ApiException.class);

        // Run the test
        assertThrows(LanguageServiceException.class, () -> languageAnalyzerUnderTest.getEntitiesMentioned("text"));
    }
}
                
              
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.recordDealsRetrieved(sortKey);
            return deals;
        } catch (final NetworkException e) {
            metricAdapter.recordNetworkException(sortKey, e);
            return Collections.emptyList();
        } catch (final ServiceException e) {
            metricAdapter.recordServiceException(sortKey, e);
            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.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@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 and verify the results
        mockMvc.perform(get("/deals/current")
                        .param("sortKey", "sortKey")
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().json("{}", true));
        verify(mockMetricAdapter).recordDealsRetrieved("sortKey");
    }

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

        // Run the test and verify the results
        mockMvc.perform(get("/deals/current")
                        .param("sortKey", "sortKey")
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().json("[]", true));
        verify(mockMetricAdapter).recordDealsRetrieved("sortKey");
    }

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

        // Run the test and verify the results
        mockMvc.perform(get("/deals/current")
                        .param("sortKey", "sortKey")
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().json("[]", true));
        verify(mockMetricAdapter).recordNetworkException(eq("sortKey"), any(NetworkException.class));
    }

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

        // Run the test and verify the results
        mockMvc.perform(get("/deals/current")
                        .param("sortKey", "sortKey")
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().json("[]", true));
        verify(mockMetricAdapter).recordServiceException(eq("sortKey"), any(ServiceException.class));
    }
}
                
              
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) {
        deal.setId(dealForm.getId());
        deal.setProductName(dealForm.getProductName());
        deal.setPrice(dealForm.getPrice());
        deal.setQuantityRemaining(dealForm.getQuantityRemaining());
        deal.setImageUrl(dealForm.getImageUrl());
    }
}
                  
                
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.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;

@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 and verify the results
        mockMvc.perform(get("/admin/deals")
                        .accept(MediaType.TEXT_HTML))
                .andExpect(status().isOk())
                .andExpect(content().string("expectedResponse"));
    }

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

        // Run the test and verify the results
        mockMvc.perform(get("/admin/deals")
                        .accept(MediaType.TEXT_HTML))
                .andExpect(status().isOk())
                .andExpect(content().string("expectedResponse"));
    }

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

        // Run the test and verify the results
        mockMvc.perform(get("/admin/deals")
                        .accept(MediaType.TEXT_HTML))
                .andExpect(status().is5xxServerError())
                .andExpect(content().string("expectedResponse"));
    }

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

        // Run the test and verify the results
        mockMvc.perform(get("/admin/deals")
                        .accept(MediaType.TEXT_HTML))
                .andExpect(status().is5xxServerError())
                .andExpect(content().string("expectedResponse"));
    }

    @Test
    void testNewDeal() throws Exception {
        // Setup
        // Run the test and verify the results
        mockMvc.perform(get("/admin/deals/new")
                        .accept(MediaType.TEXT_HTML))
                .andExpect(status().isOk())
                .andExpect(content().string("expectedResponse"));
    }

    @Test
    void testCreateNewDeal() throws Exception {
        // Setup
        // Run the test and verify the results
        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))
                .andExpect(status().isOk())
                .andExpect(content().string("expectedResponse"));

        // Confirm DealsStore.save(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        verify(mockDealsStore).save(deal);
    }

    @Test
    void testCreateNewDeal_DealsStoreThrowsNetworkException() throws Exception {
        // Setup
        // Configure DealsStore.save(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        doThrow(NetworkException.class).when(mockDealsStore).save(deal);

        // Run the test and verify the results
        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))
                .andExpect(status().is5xxServerError())
                .andExpect(content().string("expectedResponse"));
    }

    @Test
    void testCreateNewDeal_DealsStoreThrowsServiceException() throws Exception {
        // Setup
        // Configure DealsStore.save(...).
        final Deal deal = new Deal();
        deal.setId("id");
        deal.setProductName("productName");
        deal.setPrice(new BigDecimal("0.00"));
        deal.setQuantityRemaining(0);
        deal.setImageUrl("imageUrl");
        doThrow(ServiceException.class).when(mockDealsStore).save(deal);

        // Run the test and verify the results
        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))
                .andExpect(status().is5xxServerError())
                .andExpect(content().string("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;
    private final MetricAdapter metricAdapter;

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

    @GetMapping
    public String index(final Model model) {
        // Perform the service calls in parallel 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());
            Log.info("getDealsCall() call succeeded.");
            metricAdapter.recordGetDealsCallSuccess();
        } catch (ExecutionException | InterruptedException e) {
            metricAdapter.recordGetDealsException(e);
            Log.log(Level.WARNING, "Exception querying deals service", e);
        }
        try {
            model.addAttribute("recentOrders", recentOrdersFuture.get());
            Log.info("getRecentOrders() call succeeded.");
            metricAdapter.recordGetRecentOrdersCallSuccess();
        } catch (final ExecutionException | InterruptedException e) {
            Log.log(Level.WARNING, "Exception querying ordering service", e);
            metricAdapter.recordGetRecentOrdersException(e);
        }
        return "index";
    }

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

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.time.LocalDateTime;
import java.time.ZoneOffset;
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.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@WebMvcTest(IndexController.class)
class IndexControllerTest {

    @Autowired
    private MockMvc mockMvc;

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

    @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(LocalDateTime.of(2020, 1, 1, 0, 0, 0, 0).toInstant(ZoneOffset.UTC));
        final Product product = new Product();
        product.setId("id");
        order.setProducts(List.of(product));
        final CompletableFuture<List<Order>> listCompletableFuture1 = CompletableFuture.completedFuture(List.of(order));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listCompletableFuture1);

        // Run the test and verify the results
        mockMvc.perform(get("/")
                        .accept(MediaType.TEXT_HTML))
                .andExpect(status().isOk())
                .andExpect(content().string("expectedResponse"));

        verify(mockMetricAdapter).recordGetDealsCallSuccess();
        verify(mockMetricAdapter).recordGetRecentOrdersCallSuccess();
    }

    @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(LocalDateTime.of(2020, 1, 1, 0, 0, 0, 0).toInstant(ZoneOffset.UTC));
        final Product product = new Product();
        product.setId("id");
        order.setProducts(List.of(product));
        final CompletableFuture<List<Order>> listCompletableFuture1 = CompletableFuture.completedFuture(List.of(order));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listCompletableFuture1);

        // Run the test and verify the results
        mockMvc.perform(get("/")
                        .accept(MediaType.TEXT_HTML))
                .andExpect(status().isOk())
                .andExpect(content().string("expectedResponse"));
        verify(mockMetricAdapter).recordGetDealsCallSuccess();
        verify(mockMetricAdapter).recordGetRecentOrdersCallSuccess();
    }

    @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(LocalDateTime.of(2020, 1, 1, 0, 0, 0, 0).toInstant(ZoneOffset.UTC));
        final Product product = new Product();
        product.setId("id");
        order.setProducts(List.of(product));
        final CompletableFuture<List<Order>> listCompletableFuture1 = CompletableFuture.completedFuture(List.of(order));
        when(mockOrdersService.getRecentOrders("customerId")).thenReturn(listCompletableFuture1);

        // Run the test and verify the results
        mockMvc.perform(get("/")
                        .accept(MediaType.TEXT_HTML))
                .andExpect(status().isOk())
                .andExpect(content().string("expectedResponse"));
        verify(mockMetricAdapter).recordGetDealsException(any(Exception.class));
        verify(mockMetricAdapter).recordGetRecentOrdersCallSuccess();
    }

    @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 and verify the results
        mockMvc.perform(get("/")
                        .accept(MediaType.TEXT_HTML))
                .andExpect(status().isOk())
                .andExpect(content().string("expectedResponse"));
        verify(mockMetricAdapter).recordGetDealsCallSuccess();
        verify(mockMetricAdapter).recordGetRecentOrdersCallSuccess();
    }

    @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 and verify the results
        mockMvc.perform(get("/")
                        .accept(MediaType.TEXT_HTML))
                .andExpect(status().isOk())
                .andExpect(content().string("expectedResponse"));
        verify(mockMetricAdapter).recordGetDealsCallSuccess();
        verify(mockMetricAdapter).recordGetRecentOrdersException(any(Exception.class));
    }
}
                
              
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 {

    @Test
    void testReplaceFirst() {
        assertEquals("text", StringUtils.replaceFirst("text", "regex", "replacement"));
        assertThrows(PatternSyntaxException.class, () -> StringUtils.replaceFirst("text", "regex", "replacement"));
    }
}
                
              
Generated Test Class
<
Static Factory Methods
The source class is a Uri class that represents a website Uri. The Uri is instantiated by invoking the static factory method: parse(..). This is similar to the sealed abstract class pattern used in the Android Uri class.

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

import java.util.Map;

public abstract 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("schema", result.getSchema());
        assertEquals("authority", result.getAuthority());
        assertEquals("path", result.getPath());
        assertEquals(Map.ofEntries(Map.entry("value", "value")), result.getQueryParams());
    }

    @Test
    void testParse_ThrowsUriParseException() {
        // Setup
        // Run the test
        assertThrows(UriParseException.class, () -> Uri.parse("theUri"));
    }
}
                
              
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.assertFalse;

class JavaVersionTest {

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

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

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

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

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

Forum

The Squaretest forum has moved to GitHub Discussions!

Legacy Forum

The legacy forum is available at the Legacy Forum Archive.

Report Bugs

Track and report bugs and other issues with Squaretest on GitHub.
Individual License
$35
BUY
Business License
$55per seat
BUY
Licenses Are Perpetual
Both licenses are perpetual, meaning they never expire.
Individual vs Business
An individual license has your name on it. You can use it to install Squaretest on any device on which you are the primary user. A business 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 or she likes.
Free Trial
You can try Squaretest for free for 30 days. Please follow the instructions in the user guide to install the plugin and begin the trial.
Offline License Validation
Squaretest licenses are validated offline. They can be used in environments that are not connected to the internet.
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 $138,229.92.
  • The average developer works 8 hours per day and has 3-weeks (15 business days) of paid vacation/PTO and 7 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 for a standard Java component.
Calculations
  • The cost of 1 developer-day is $580.80 = $138,229.92 / (260 - 15 - 7).
  • The cost of 1 developer-hour is $72.60 = $580.80 / 8.
  • Number of hours needed for Squaretest to pay for itself 0.76 hours = 55 / 72.60.
  • Number of new test classes for standard components needed to pay for itself: 3.8 = 0.76 / 0.2
  • Squaretest will pay for itself when the user creates 4 new test classes for standard Java components.
Notes
The spreadsheet with the assumptions, calculations and sources is available in Squaretest Cost Savings V2. You can download the spreadsheet 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.4.1 of the Apache Velocity Engine.
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 never sends your code to the cloud. Squaretest will anonymously send usage data to the cloud if you have allowed it as described above. Squaretest also sends requests to the licensing system; these requests include a unique identifier from your license. 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 Nathan Shevick, a 6+ year software developer. Nathan 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.

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 Individual 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 1,000 users.