Mockito Verify Returns True Even Though Method Wasn t Called Again
When information technology comes to true unit of measurement tests, having a mocking framework such as Spock for Java is essential. Using a mocking framework ensures that your unit tests are fast, self-contained and deterministic. A mocking framework can assistance you lot fake external systems, pre-programme your classes with expected responses, and exam hard-to-replicate error conditions.
There are several mocking frameworks in the Java world, just the most popular one is Mockito. Our previous mocking tutorial is a dandy introduction to Mockito if you would like a detailed tutorial on using it.
In this tutorial, we will cover the Spock testing framework, an emerging framework that can be used to test both Coffee and Groovy code. Unlike Mockito, Spock is a complete testing framework that can function on its own (Mockito works in add-on to JUnit).
For the lawmaking examples, we will employ the aforementioned situations that were presented in the Mockito tutorial. This will allow for easy comparison between the two frameworks. If you ever wanted to see how Spock competes against the Junit/Mockito philharmonic, you will detect this tutorial specially interesting.
Nosotros will cover:
- Downloading and setting upwards Spock—the "batteries included" testing framework for both Java and Groovy
- Some very cursory theory on the goals of Spock,
- Stubbing return data from methods,
- Verifying interactions,
- Capturing arguments, and,
- Returning custom mocked responses.
Observe that the tutorial volition focus exclusively on testing Java code. Even though Spock can likewise piece of work with Groovy code, in this tutorial we will focus on Java unit tests. Spock can test both Coffee and Groovy, but in the case of Groovy, it has some additional capabilities that nosotros will not cover here.
Prerequisites
It is assumed that you already have a Coffee project and you want to write unit tests for it. We volition need:
- A sample Java project synthetic in a well-disciplined manner, i.eastward. using Dependency Injection,
- A valid
pom.xmlfile that builds the project, - Maven installed—the command
mvnshould be available in your command line, and - Net access to download Maven dependencies.
The Java project may or may not have existing JUnit tests. Spock tests can be added to the project without whatsoever negative affect on the existing JUnit tests. Both kinds of tests will run when the Maven examination goal is executed.
Not bad knowledge is NOT required, as the Spock tests will be written in a Groovy style that is very shut to Java. However, for some advanced examples, it would be beneficial to know Coffee 8 lambda expressions equally they will exist similar to the Not bad closures in this tutorial.
It is likewise assumed that we already know our way around basic Maven builds. If not, feel gratuitous to consult its official documentation offset.
Mockito noesis is non strictly required. We volition cover some differences between Mockito and Spock that will be useful if you are already a Mockito veteran.
Setting Upwards Spock
Spock is already distributed via Maven cardinal, so using it in a Java forward is a painless procedure. We just demand to alter the pom.xml and add the following dependencies:
<dependency> <groupId>org.spockframework</groupId> <artifactId>spock-core</artifactId> <version>ane.1-slap-up-ii.4</version> <scope>test</scope> </dependency> <dependency> <!-- enables mocking of classes (in addition to interfaces) --> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> <version>1.half dozen.v</version> <scope>test</scope> </dependency> <dependency> <!-- enables mocking of classes without default constructor (together with CGLIB) --> <groupId>org.objenesis</groupId> <artifactId>objenesis</artifactId> <version>ii.5.1</version> <scope>exam</scope> </dependency> The reason why we demand three dependencies instead of only ane is that the actress libraries are needed to "replicate" some of the needed born Bully functionality, in instance if nosotros wanted to write unit tests for a Groovy awarding.
In club to integrate Spock into the Maven lifecycle, we also demand the post-obit additions in the same pom file:
<build> <plugins> <plugin> <groupId>org.codehaus.gmavenplus</groupId> <artifactId>gmavenplus-plugin</artifactId> <version>1.5</version> <executions> <execution> <goals> <goal>compile</goal> <goal>testCompile</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>two.eighteen.1</version> <configuration> <useFile>simulated</useFile> <includes> <include>**/*Spec.java</include> <include>**/*Examination.java</include> </includes> </configuration> </plugin> </plugins> </build> The Surefire plugin configuration ensures that both JUnit and Spock unit of measurement tests are honored by Maven.
This concludes the setup. Now, whenever we run mvn examination, both kinds of tests volition run and be presented in reports (even including code coverage if you have information technology enabled in your pom file).
Spock unit of measurement tests will need to be placed in the src/test/groovy/ folder, while JUnit tests (if any) are nonetheless in src/test/coffee/ as per Maven guidelines.
Spock and the Java Ecosystem
If you are already a veteran of JUnit and contrasted testing tools, you might wonder why Spock was created in the commencement place. Aren't the existing testing frameworks capable of dealing with all of our testing needs?
The answer is that Spock was created to embrace the full testing lifecycle of a Java Enterprise awarding. The existing tools have a long history and come up with several legacy features that cannot always keep up with newer testing practices. The most evident case of this is the fact that JUnit covers only evidently unit testing and cypher else. If you need to mock some services or wish to employ Beliefs-driven evolution, JUnit is simply not enough. You are forced to add more testing frameworks into the mix, each i with its own idiosyncrasies and bug.
Spock takes a step back and offers you all the testing facilities you might need during the full testing lifecycle. It comes with congenital-in mocking and stubbing and several actress testing annotations created exclusively for integration tests.
At the same time, considering Spock is a newer testing framework, it had the time to observe common pitfalls of the existing frameworks and either set them or offer a more elegant workaround. Explaining all the advantages of Spock over existing solutions is out of the scope of this article. A more detailed comparison between Spock and the JUnit/Mockito combo tin be found in the Spock vs JUnit article.
In the context of mocking, Spock offers four major advantages:
- Spock doesn't need special constructs for capturing arguments and creating mocked answers. Information technology uses Not bad closures, which are similar to Java 8 lambda expressions.
- Mockito has a limitation with argument matchers. If you use matchers in a method, and then all arguments need to take matchers. Spock does non suffer from this limitation, and you can mix and lucifer real arguments with argument matcher.
- Spock makes a stardom between stubs and mocks, making unit of measurement tests slightly more readable.
- Spock presents much more detailed mistake letters when expected mock invocations are non institute.
A Word on Mocking and Stubbing
The theory behind mocking and stubbing was already explained in the previous article under the department "The Need for Mocks and Stubs". We are not going to repeat it here. In summary, we use mocks to isolate the class nether test and examine it in a completely controlled environment. Mutual targets for mocking are:
- Database connections,
- Web services,
- Classes that are slow,
- Classes with side effects, and
- Classes with non-deterministic behavior.
We will cover two kinds of mock objects. Stubs are false classes that come up with preprogrammed return values. Mocks are faux classes that we can examine subsequently a exam has finished and see which methods were run or not.
Spock makes a articulate distinction between the two as mocks and stubs, as we will run across in the sections to follow.
Semaphore as well provides tutorials for mocking in other languages if your interests go across Java:
- Mocking in Python
- Mocking in Reddish
- Mocking in Javascript
Basic Stubbing with Spock
In our example application, we have a class that reads a customer from the database and forms their full name.
Here is the code for the customer:
@Entity public course Customer { @Id @GeneratedValue(strategy = GenerationType.Motorcar) individual long id; individual String firstName; individual String lastName; //...getters and setters redacted for brevity... } and here is our business course:
public class CustomerReader { @PersistenceContext private EntityManager entityManager; public Cord findFullName(Long customerID){ Customer client = entityManager.find(Customer.course, customerID); return customer.getFirstName() +" "+customer.getLastName(); } } This class reads customers from the database via the EntityManager. Nosotros will examination it by stubbing the EntityManager and then that we can decide what gets returned without having a real database.
Here is the Spock unit exam:
public form CustomerReaderSpec extends spock.lang.Specification{ public void "client total name is formed from first name and concluding name"() { given: "a client with case proper noun values" Customer sampleCustomer = new Customer() sampleCustomer.setFirstName("Susan") sampleCustomer.setLastName("Ivanova") and: "an entity manager that always returns this customer" EntityManager entityManager = Stub(EntityManager.class) entityManager.observe(Client.class,1L) >> sampleCustomer and: "a customer reader which is the class under test" CustomerReader customerReader = new CustomerReader() customerReader.setEntityManager(entityManager) when: "we ask for the full name of the customer" String fullName = customerReader.findFullName(1L) then: "we get both the showtime and the last name" fullName == "Susan Ivanova" } } This file is called CustomerReaderSpec.groovy, and it should exist placed in the folder src/test/peachy under the aforementioned Java package as the course under test. We take instructed Spock to run unit tests that end in *Spec in the Maven pom file, as described in the previous section.
Even if you accept never seen Groovy/Spock before, the syntax of the unit test should be familiar, as the code is deliberately written to exist Java-like.
First of all, we have named our unit test using a full sentence that explains its purpose (customer total proper noun is first name plus last proper name). With Spock, y'all are free to utilise proper English explanations for your unit tests. These sentences also appear in unit test reports, and then they are very valuable for other people in your organization (e.g. Project Managers), equally they can understand what a unit of measurement test does with zero Java/Dandy cognition.
More importantly, the test content itself is marked with given, and, when, then labels that showcase the BDD spirit of Spock. These labels are called blocks in Spock parlance, and they logically split the unit examination to create a well-defined construction. The strings side by side to each characterization serve equally a human-readable explanation of the associated lawmaking cake.
The idea is that somebody tin can focus just on these labels and understand what the unit of measurement tests dos without actually looking at the code. In this particular example, the following blocks are contained:
- given: "a client with example name values"
- and: "an entity manager that always returns this customer"
- and: "a customer reader which is the class under test"
- when: "nosotros ask for the full proper noun of the customer"
- so: "nosotros get both the first and the last proper noun"
Reading the block descriptions creates an English sentence that serves as a mini-specification of what the test does. The labels tin be normal strings, and then you should strive to proper noun them according to your business domain and brainchild depth that suits you. Ideally, you should apply full sentences to explain what each cake does in a high-level style.
The given: block contains but some Coffee lawmaking that creates a sample client. The first and: block is where nosotros actually create a fake object. In this particular case, we create a stub using the static method Stub() that Spock offers. We essentially tell Spock that it will need to create a false object for the EntityManager form.
The most important line of the whole test is the next 1. The line entityManager.find(Customer.class,1L) >> sampleCustomer instructs Spock what to do when the observe() method of the stub is called.
The caret grapheme means "render" in Spock parlance. The whole statement says: "when the entityManager find() method is called with arguments Customer class and 1, return our sample customer".
If you know how Mockito works, the equivalent line would exist: when(entityManager.find(Customer.class,1L)).thenReturn(sampleCustomer);
We've now both created a Stub object with Spock, and also instructed it with a dummy render result. Next, we create our CustomerReader reader object and pass every bit a dependency the fake object. From at present on, the CustomerReader course will function without understanding that the EntityManager is non a real one.
In the when: block, we call our test method in the usual Java manner. The final block is the and then: cake. This is the block that decides if the test will fail or not. Different Junit, Spock does not use assert statements. Instead, it expects normal boolean statements. Statements in the so: cake will be evaluated by Spock as boolean, and if all of them are true, the examination will laissez passer. If any of them fail, the examination will neglect.
Notice also that no argument has a semicolon at the end of the line. Unlike Coffee, Groovy does not crave semicolons.
With the test lawmaking in identify, nosotros tin run this Spock unit test either from the control line (using the mvn test command), or via our favorite IDE. Here is an example with Eclipse.
As far as Eclipse is concerned, the Spock test is handled in exactly the same way as a JUnit test would be.
The test result shows the title correctly as a total English language sentence.
Grouping Multiple Unit of measurement Tests for the Same Grade Under Exam
In the previous section, we had a single unit test in a single file. In a real project, we volition probably have multiple unit tests for the same class nether test in order to evaluate multiple scenarios and conditions.
In those cases, it makes sense to motion the stub creation process to a reusable method, removing code duplication. Similar to the @Before note in JUnit, Spock besides allows the extraction of common setup code into a method that will run before each unit examination.
You might accept already noticed that our CustomerReader form is non correct, as it does not handle the null example, i.e. the given database ID does not exist as an object in the DB.
Let's create a unit test that covers this scenario as well.
public class CustomerReader2Spec extends spock.lang.Specification{ //Class to be tested private CustomerReader customerReader; //Dependencies individual EntityManager entityManager; /** * Runs earlier each test method, like the JUnit Before * annotation */ public void setup(){ customerReader = new CustomerReader(); entityManager = Stub(EntityManager.grade); customerReader.setEntityManager(entityManager); } public void "customer full name is formed from kickoff proper name and last proper name"() { given: "a customer with case proper noun values" Customer sampleCustomer = new Client() sampleCustomer.setFirstName("Susan") sampleCustomer.setLastName("Ivanova") and: "an entity manager that always returns this customer" entityManager.find(Client.class,1L) >> sampleCustomer when: "we ask for the full proper name of the customer" Cord fullName = customerReader.findFullName(1L) then: "we become both starting time and terminal name" fullName == "Susan Ivanova" } public void "customer is not in the database"(){ given: "the database has no record for the customer" entityManager.find(Customer.class,1L) >> null when: "nosotros enquire for the total name of the customer" String fullName = customerReader.findFullName(1L) and then: "the empty cord should be returned" fullName == "" } } The method named setup() will be executed by Spock before each individual proper noun. This functionality is detected by the name of the method itself (at that place is no Spock notation for this).
Apart from extracting the common code for creating our test class and its mocked dependencies, we accept also added a 2nd scenario for the example when the customer is non in the database.
For this scenario, the stubbing line is changed to entityManager.find(Customer.class,1L) >> zilch. This line means: "when the notice() method is chosen with these arguments, and then return nothing".
In true TDD fashion, we have created the unit tests earlier the actual implementation. If you run our unit test, the second test method volition fail. Eclipse should still show the names of the tests as full sentences.
Equally an practice, feel free to correct the CustomerReader implementation and likewise add together extra unit of measurement tests when the starting time and/or last proper noun are null themselves.
To proceeds total reward of the individual Spock blocks, you tin can also utilise the external project of Spock reports.
Here is a sample report:
You lot tin can discover information on how to use the reports in the README file.
Basic Mocking with Spock
In all the examples then far, we take only seen Spock stubs (i.due east. classes that hardcoded return values). For a mocking example, let'due south assume that we have the post-obit course in our application:
public class LateInvoiceNotifier { individual concluding EmailSender emailSender; private terminal InvoiceStorage invoiceStorage; public LateInvoiceNotifier(concluding EmailSender emailSender, final InvoiceStorage invoiceStorage){ this.emailSender = emailSender; this.invoiceStorage = invoiceStorage; } public void notifyIfLate(Client customer) { if(invoiceStorage.hasOutstandingInvoice(customer)){ emailSender.sendEmail(customer); } } } This class has two external dependencies, a course that sends emails and an invoice database. It checks for late customer invoices and sends customers an email if an invoice is late.
We desire to exam the method notifyIfLate() and ensure that emails are sent to a customer merely if they have outstanding invoices. Since the method does not take a return value, the only fashion to verify if it runs or non is to use a mock.
We volition mock both InvoiceStorage and EmailSender, run the unit of measurement test and examine what interactions took identify afterward the test has finished.
We demand to exam two scenarios. In the beginning one, the customer has an outstanding invoice (and thus an e-mail should exist sent). In the second one, the client has no awaiting invoices. Hither is the Spock code:
public class LateInvoiceNotifierSpec extends spock.lang.Specification{ //Class to be tested private LateInvoiceNotifier lateInvoiceNotifier //Dependencies (will be mocked) private EmailSender emailSender private InvoiceStorage invoiceStorage //Test data private Customer sampleCustomer /** * Runs before each examination method, similar the JUnit Before * annotation */ public void setup(){ invoiceStorage = Stub(InvoiceStorage.class) emailSender = Mock(EmailSender.class) lateInvoiceNotifier = new LateInvoiceNotifier(emailSender,invoiceStorage); sampleCustomer = new Client() sampleCustomer.setFirstName("Susan") sampleCustomer.setLastName("Ivanova") } public void "a late invoice should trigger an email"() { given: "a customer with a late invoice" invoiceStorage.hasOutstandingInvoice(sampleCustomer) >> true when: "we check if an email should be sent" lateInvoiceNotifier.notifyIfLate(sampleCustomer) then: "the client is indeed emailed" ane * emailSender.sendEmail(sampleCustomer) } public void "no late invoices"() { given: "a customer with good standing" invoiceStorage.hasOutstandingInvoice(sampleCustomer) >> false when: "we check if an email should be sent" lateInvoiceNotifier.notifyIfLate(sampleCustomer) then: "an email is never sent out" 0 * emailSender.sendEmail(sampleCustomer) } } The first dependency, InvoiceStorage, is used as a stub. This is why we apply the caret syntax as shown in the previous section. For the first test, we assume the customer has an outstanding invoice (line invoiceStorage.hasOutstandingInvoice(sampleCustomer) >> true). For the second test, no belatedly invoice is present (line invoiceStorage.hasOutstandingInvoice(sampleCustomer) >> false.)
The 2nd dependency – EmailSender is a bit different. At the end of the exam, we need to know if an email was sent or not. The only way to do this is to cheque how many times the method sendEmail() was called using a mock.
Spock supports the creation of mocks using the static Mock() method. Hither is the respective line:
emailSender = Mock(EmailSender.class); When running a unit test, Spock keeps track of all the invocations that happen with mocked objects. At the end of the test, we can query these invocations with the post-obit Spock syntax:
N * mockedObject.method(arguments) This line means: "after this test is finished, this method of mockedObject should have been called Northward times with these arguments". If this has happened, the test volition pass. Otherwise, Spock will neglect the test.
The verification lines are placed within the then: block of each test, right at the stop of the examination method.
In our case, the line 1 * emailSender.sendEmail(sampleCustomer) ways: "once this examination has finished, the sendEmail() method should have been called 1 time with the sampleCustomer class every bit an argument. This is the scenario when an email should be sent. In the 2d scenario, the number of times is zero because no e-mail should be sent.
If you already know Mockito, these ii Spock lines map to verify(emailSender, times(1)).sendEmail(sampleCustomer); and verify(emailSender, times(0)).sendEmail(sampleCustomer); respectively.
Spock is smart plenty to monitor the expected invocations, and give a clear mistake message when things become incorrect. For example, let's assume that we have a bug in the code that does not send reminders to customers when they take outstanding invoices. The examination will neglect, and Spock will nowadays the following error message:
Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.015 sec <<< FAILURE! - in com.codepipes.mocking.LateInvoiceNotifierSpec a late invoice should trigger an electronic mail(com.codepipes.mocking.LateInvoiceNotifierSpec) Fourth dimension elapsed: 0 sec <<< FAILURE! org.spockframework.mock.TooFewInvocationsError: Too few invocations for: ane * emailSender.sendEmail(sampleCustomer) (0 invocations) In the mistake bulletin, Spock explains how we requested 1 telephone call for the method sendEmail(), just that method was never called – 0 invocations.
Verifying Mocked Object Arguments
The previous example was relatively simple, we just verified whether a single method was called or not. Sometimes we need more than item, and instead of looking only at the method phone call itself, we are too interested in the arguments.
As an example, let's assume that the analytics section wants more than extensive metrics, and has asked y'all to implement an extra machinery, where several important events for a customer are recorded and later on analyzed.
Here is the source code of the Event that the metrics solution supports:
public class Effect { public enum Blazon {REMINDER_SENT, REGISTRATION, INVOICE_ISSUED, PAYMENT, SETTLEMENT}; private Type type; private String customerName; individual LocalDate timestamp; //..getters and setters redacted for brevity... } The LateInvoiceNotifier class is then augmented with an EventRecorder dependency and nosotros want to write a unit test that verifies that the event recorded:
- is of blazon
REMINDER_SENT, - has the correct customer name, and
- contains a timestamp.
Spock supports examining method arguments using Smashing closures. Great closures are very similar to Java 8 lambda expressions, so you don't demand any special knowledge to empathise them if you have already worked with Java viii. They both apply the -> to marking a closure, so Java and Bang-up code are mostly very close to each other.
Here is the Spock examination that not only verifies that the email event was recorded, but also checks its values:
public class EventCheckSpec extends spock.lang.Specification{ //Class to exist tested private LateInvoiceNotifier lateInvoiceNotifier; //Dependencies (will be mocked) private EmailSender emailSender; private InvoiceStorage invoiceStorage; private EventRecorder eventRecorder; //Test information private Customer sampleCustomer; /** * Runs before each examination method, like the JUnit Before * annotation */ public void setup(){ invoiceStorage = Stub(InvoiceStorage.grade) emailSender = Mock(EmailSender.form) eventRecorder = Mock(EventRecorder.class) lateInvoiceNotifier = new LateInvoiceNotifier(emailSender,invoiceStorage,eventRecorder); sampleCustomer = new Customer(); sampleCustomer.setFirstName("Susan") sampleCustomer.setLastName("Ivanova") } public void "email almost late invoice should contain customer details"() { given: "a customer with a late invoice" invoiceStorage.hasOutstandingInvoice(sampleCustomer) >> true when: "we cheque if an e-mail should be sent" lateInvoiceNotifier.notifyIfLate(sampleCustomer) then: "the client is indeed emailed" i * emailSender.sendEmail(sampleCustomer) and: "the event is recorded with the respective details" ane * eventRecorder.recordEvent({ consequence -> event.getTimestamp() != zip && upshot.getType() == Consequence.Type.REMINDER_SENT && event.getCustomerName() == "Susan Ivanova" }) } } Our class nether test LateInvoiceNotifier now has 3 dependencies:
-
InvoiceStorageis just used as a helper, so nosotros stub information technology, -
EmailSenderwill exist used to verify that an email was sent. We create a Mock for information technology, and, -
EventRecordervolition also exist used to verify the result that was emitted. We too create a mock for information technology.
The cosmos of these 3 mocks happens in the setup() method. Our class under test now has iii fake dependencies, and we have total control of all input and output that happens during the unit test.
The unit test itself has a slightly dissimilar construction from the ones nosotros accept seen before. This time, we have the following blocks: given, when, then, and.
The second and: block later the then: cake is used because the unit of measurement test really tests ii related deportment. Get-go of all, information technology verifies that the email was indeed sent equally in the previous department. This is the line 1 * emailSender.sendEmail(sampleCustomer);. This line is the same every bit with the previous section.
We as well need to verify that an event has been created (along with the contents of the consequence). Nosotros employ an and: block at the end of the exam to practice this. The -> graphic symbol denotes a Groovy closure. The last line of the test means:
- "Verify that the
recordEvent()method of theeventRecorderform was called 1 time, - and utilize a closure to capture the argument that was used,
- and name the argument
event, - and verify that the statement had a non-null
timestampproperty, - and a
Blazon.REMINDER_SENTtype holding, - and a customerName property equal to "Susan Ivanova".
If all the above are true, the test will succeed. If any of these statements is false, the whole test will fail. Spock is so smart that it can detect the deviation between an invocation that has arguments that are like, only not exactly the same.
Let'southward assume that nosotros take a bug in our application, and that the timestamp holding is not correctly prepare. Spock will present the following test fault:
e-mail about late invoice should contain customer details(com.codepipes.mocking.EventCheckSpec) Time elapsed: 0.126 sec <<< FAILURE! org.spockframework.mock.TooFewInvocationsError: Likewise few invocations for: 1 * eventRecorder.recordEvent({ event -> event.getTimestamp() != cypher && issue.getType() == Event.Type.REMINDER_SENT && event.getCustomerName() == "Susan Ivanova" }) (0 invocations) Unmatched invocations (ordered past similarity): ane * eventRecorder.recordEvent(com.codepipes.mocking.Event@31198ceb) Here, Spock tells u.s.a. that, while our method was indeed called in one case, it was not called with the arguments we requested.
Forming Dynamic Responses for Mocks
The previous examples of Spock unit tests will cover most of your testing needs. We will now embrace some advanced Spock examples that deal with dynamic manipulations of arguments and responses from mocks.
Again, Spock is based on Groovy closures for both of these features. If you know your fashion around Coffee 8 lambda expressions, then information technology should be very easy to follow.
Withal, go on in mind that dynamic manipulation of arguments and responses is an advanced technique that will be needed only for some very specific corner cases in your unit of measurement tests. If you have a choice, it is all-time to return predefined results in your mocks/stubs, so that the test is more readable. Use dynamic responses only as a concluding resort in your unit of measurement tests.
Dynamic Manipulation of Arguments with Spock
Let's run into an example where we just want to alter the argument itself. We'll assume that you want to exam the post-obit class:
public class CustomerDao { @PersistenceContext private EntityManager entityManager; individual Logger logger; public void saveCustomer(Cord firstName, String lastName) { if(firstName == zip || lastName==zip) { logger.fault("Missing customer information"); throw new IllegalArgumentException(); } Customer client = new Customer(firstName,lastName); entityManager.persist(customer); entityManager.flush(); logger.info("Saved customer with id {}", customer.getId()); } } You should instantly see why writing a unit test for this class is a bit tricky. Even though the DAO logic itself is very basic, the fact that once the customer is saved using the persist method, its database ID is sent to the logger presents a trouble. For this contrived example, the code will work simply fine in the real system, equally the database will indeed assign an ID to the object as soon equally it is saved.
How can we replicate this processing in our unit test? The persist method does not return an argument, so we cannot mock information technology using Spock's >> syntax.
Spock can withal create a unit exam for this scenario with the following examination:
public class CustomerDaoSpec extends spock.lang.Specification{ // Course to be tested individual CustomerDao customerDao; // Dependencies (will exist mocked) private EntityManager entityManager private Logger logger //Test data private Customer sampleCustomer /** * Runs before each test method, like the JUnit Before * annotation */ public void setup(){ customerDao = new CustomerDao(); entityManager = Stub(EntityManager.class) customerDao.setEntityManager(entityManager) logger = Mock(Logger.class) customerDao.setLogger(logger) } public void "customer IDs are logged whenever they are saved in the DB"() { given: "a customer dao that assigns an ID to customer" entityManager.persist( _ as Customer) >> { Customer client -> customer.setId(123L)} when: "that customer is saved in the DB" customerDao.saveCustomer("Suzan", "Ivanova") and then: "the ID is correctly logged" 1 * logger.info("Saved customer with id {}", 123L) } } As with the previous unit of measurement tests, we create ii simulated objects in the setup() method:
- The
EntityManagerclass is stubbed, and, - The
Loggerclass is mocked considering we need to verify itsinfo()method.
The most important line of the whole unit of measurement exam is the following:
entityManager.persist( _ every bit Customer) >> { Customer client -> customer.setId(123L)} Let'south break this line into two parts, the one earlier the >> operator, and the ane after. The first part uses the underscore character as an argument. The underscore graphic symbol is a special character in Spock, and it ways "whatsoever". It is used as an argument matcher that can match any value of the argument. The syntax as Customer is another special Spock construct that makes the examination a fleck more strict past ensuring that the argument is indeed a Customer class.
Therefore, the showtime part of the statement matches the call of the persist() method with whatsoever kind of statement that is a Client. The equivalent matcher in Mockito would be when(entityManager).persist(any(Customer.class).
In all the Spock examples nosotros have seen so far, the >> operator means "then return". In this particular instance, the persist() method doesn't return anything. Therefore, we can think the >> character as "then exercise". The second role of the argument is a Groovy closure (denoted past the -> grapheme), and it means "take the customer statement, and execute its setId() method with an argument of 123L".
This is all that is needed to create dynamic responses in Spock. Mockito would need a special Answer construct here.
The concluding part of the test (the and so: cake) is the same as we accept seen in previous examples. It only verifies that the info() method was executed once with the correct arguments and more specifically with the ID equal to 123 which was stubbed in the when: block.
Dynamic Responses Based on Arguments with Spock
Every bit a grand finale, nosotros volition run into an extreme unit examination where the answer of a mock depends on the argument. Let's assume that you want to test the following class:
public grade MassUserRegistration { private final EventRecorder eventRecorder; individual terminal UserRepository userRepository; public MassUserRegistration(concluding EventRecorder eventRecorder, final UserRepository userRepository) { this.eventRecorder = eventRecorder; this.userRepository = userRepository; } private void register(Cord firstName, String lastName) { Client newCustomer = userRepository.saveCustomer(firstName, lastName); Event event = new Event(); event.setTimestamp(newCustomer.getSince()); effect.setCustomerName(newCustomer.getFullName()); event.setType(Type.REGISTRATION); eventRecorder.recordEvent(outcome); } public void massRegister(List rawCustomerNames) { for (Customer client:rawCustomerNames) { register(customer.getFirstName(),client.getLastName()); } } } This is a class that takes a list of customers and saves them on the UserRepository. For each customer, an consequence of type REGISTRATION is likewise emitted.
We want to test the method called massRegister(), as the annals() 1 is private. In theory, we could laissez passer a listing of only one customer in our unit of measurement test, only in do, it is best to endeavour with a long list of customers. The code hither is very simple, and it does no error checking at all, simply in a production system, there might be several consistency checks before a customer is registered. A realistic unit of measurement examination would pass a huge list of customers with various problems so that all checks can exist evaluated during unit testing.
Let's say nosotros want to exam using a list of 20 customers. This time, the saveRepository method does return an argument, and so in theory, we could stub that method with the >> operator twenty times to instruct it exactly what output it should transport.
A more curtailed way is the following:
public course MassUserRegistrationSpec extends spock.lang.Specification{ //Course nether test private MassUserRegistration massUserRegistration; //Dependencies (will be mocked) private UserRepository userRepository; private EventRecorder eventRecorder; //Test data individual List sampleCustomers; /** * Runs before each examination method, like the JUnit Earlier * notation */ public void setup(){ sampleCustomers = new ArrayList<>() eventRecorder = Mock(EventRecorder.class) userRepository = Stub(UserRepository.class) userRepository.saveCustomer( _ equally Cord, _ as String) >> { String firstName, String lastName -> Customer newCustomer = new Customer(firstName, lastName) newCustomer.setFullName(firstName + " " + lastName) newCustomer.setSince(LocalDate.now()) return newCustomer } massUserRegistration = new MassUserRegistration(eventRecorder,userRepository); } public void "mass registration of users"() { given: "a list of sample Customers" sampleCustomers.add(new Customer("Susan", "Ivanova")); sampleCustomers.add(new Customer("Lyta", "Alexander")); sampleCustomers.add together(new Customer("Vir", "Cotto")); sampleCustomers.add(new Client("Stephen", "Frankling")); //[...twenty customers redacted for brevity...] when: "we register all customers at in one case" massUserRegistration.massRegister(sampleCustomers); then: "each registration event contains the correct client details" sampleCustomers.each { sampleCustomer -> 1 * eventRecorder.recordEvent({ outcome -> outcome.getTimestamp() != null && issue.getType() == Event.Type.REGISTRATION && outcome.getCustomerName() == sampleCustomer.getFirstName() + " "+ sampleCustomer.getLastName() }) } } } This Spock unit examination essentially gathers all the techniques we have seen so far in ane masterpiece. It combines uncomplicated stubbing, simple mocking, dynamic arguments and argument verification in the same file!
Let's analyze everything in plough. Our grade nether test is MassUserRegistration and has 2 dependencies:
- Grade
UserRepository. We will create a stub for information technology as we utilise it every bit a helper class - Class
EventRecorder. We will mock it because we want to verify the emission of events for each user registration.
In our setup() method we stub UserRepository using dynamic arguments:
userRepository.saveCustomer( _ as String, _ as String) >> { String firstName, String lastName -> Customer newCustomer = new Customer(firstName, lastName) newCustomer.setFullName(firstName + " " + lastName) newCustomer.setSince(LocalDate.at present()) return newCustomer } The first part before the >> operator matches the saveCustomer() method when any two arguments are passed by employing the underscore graphic symbol. To make the examination a fleck more strict nosotros make sure that the arguments are Strings (the equally String) syntax. If non-cord arguments are passed, the unit test will fail.
The second part after the >> operator instructs the stub to create a dynamic response for the two matched arguments. It uses a closure with ii statement where the starting time one is named firstName, and the second one is named lastName. These values are used for the cosmos of a new Client object.
The combination of these two parts translates to:
- Whenever the
saveCustomerof theuserRepositoryobject is called with whatsoever Strings as arguments, - proper name those arguments
firstNameandlastName, - create a new
Customerobject on the wing using those two strings in the constructor, - concatenate these two strings with space and assign the result to the
fullNameproperty of the client, - set the
sinceproperty to the current date, and, - render the
Customercreated to the method caller.
All these actions will be performed by Spock during the course of the unit test. Regardless of the size of our testing data, the UserRepository mock will always return the right response to the class under test.
In the then: block nosotros perform verification of the events for each client. First of all, we apply the Groovy each iteration that allows usa to use a closure for each Customer. This is equivalent to the Coffee viii forEach statement.
Then, we employ the same argument verification we have seen in the previous department within the closure. For each customer passed in the recordEvent method, we verify that the event emitted is of blazon Type.REGISTRATION, that the timestamp property is not null, and that the correct offset proper noun and last proper name were stored.
Discover that the unit test is written in such a way that the size of the input data is really irrelevant. We tin can expand the examination information from xx customers to 100 customers, to 1000 customers, and the mocking and verification code volition remain unchanged. This would not be the case if we had manually stubbed a unlike response for each specific customer.
Continuous Integration for Spock on Semaphore
At present that we take our tests, we tin start doing continuous integration (CI). The first step is to integrate our project'southward repository with Semaphore, which will wait for any pushes to our repository and will then run our tests for us.
Semaphore comes with an included stack of Java tools, including Maven and Gradle, assuasive u.s.a. to set up our projection with minimal effort.
Run the Spock Instance Project on Semaphore
To end the post on a practical note, let'southward endeavor the official Spock Example Projection on Semaphore.
In this section, we'll configure a CI Pipeline to build and exam an application with Maven and Spock.
- Caput to the Spock case repository and employ the Fork button to get your own re-create of the lawmaking.
- Clone the repository to your motorcar: utilize the Clone or download push button to get the repository URL and so:
$ git clone https://github.com/...your repository url... - Sign upwards for a Semaphore business relationship using the Sign up with GitHub push on the acme-right corner.
- Click on the + (plus sign) adjacent to Projects:
- Choose the spock-example repository:
- Semaphore will evidence you some starter workflows. Spock works with Emmet, Gradle and Maven. Let's endeavor Maven:
- Click on Run this Workflow to get started.
- To edit the pipeline, click on the Edit Workflow push button near the top-right corner. This will open the Workflow Builder:
The master components of the builder are:
- Pipeline: a pipeline fulfills a particular objective, for instance: testing. A pipeline organizes the catamenia of the CI/CD process, nosotros can design a complex workflow out of multiple pipelines connected together.
- Agent: the agent is the virtual machine that executes the pipeline. It consists of a Automobile Type and an OS Image. The Automobile Type defines the amount of CPUs, RAM, and storage that is available. At that place are many types to choose from.
- Blocks: blocks run 1 at a time, from left to right. A block groups jobs with a like purpose and configuration.
- Jobs: jobs contain commands that do the work. We can define multiple jobs in a block. Jobs in a block run in parallel. Once all jobs in a block consummate, the next block can begin.
The job uses some user-friendly commands provided by Semaphore:
- checkout: clones the GitHub repository to the Semaphore environment and changes the working directory. Most of our jobs volition showtime with
checkout. - sem-version: switches the active language version. In this example, we are using Coffee 8 (Java SDK ane.eight). Sem-version supports multiple languages.
Using the Enshroud
Our initial CI pipeline does its job, only we tin can better it. Nosotros take to tweak information technology a bit to:
- Utilize the Maven Wrapper (mvnw) script as recommended by the official Spock reference.
- Use a project-broad cache to speed up build time.
- Separate building from testing so it'southward easy to add together more than tests later.
Let's customize the pipeline:
- Click on the Maven block.
- Change the contents of the command box and so they await like this:
checkout cache restore sem-version java ane.viii ./mvnw bundle -Dmaven.exam.skip=true cache store - Open up the Environment Variables section.
- Add the post-obit variable past clicking on +Add env_var:
-
MAVEN_OPTS=-Dmaven.repo.local=.m2
-
We accept introduced some new concepts in this cake:
- cache: the enshroud is projection-wide storage supplied by Semaphore. The cache script scans the current directory and detects the project type, language, and the files and directories to
storeandrestore. Using the cache, we tin can avoid re-downloading the Maven dependencies each time. - Environment Variables: variables divers in the cake are fix for all its jobs. In this instance, nosotros tell Maven to find downloaded dependencies in the current
.m2directory (instead of in the user's$HOME). This is required for the cache to work.
To try the workflow:
- Click on Run the Workflow.
- Click on Start.
Add the Tests
Add together a second block to run the tests:
- Click on Edit Workflow.
- Add a new block by clicking on the + Add Block dotted grayness box.
- Name the block: "Tests"
- Change the proper name of the task to: "Spock Tests"
- Blazon the post-obit commands:
./mvnw test - Open the prologue section. Commands we type in the prologue are executed before each job in the block. Type the following set-up commands:
checkout cache restore - Open the Environment Variables section and define the
MAVEN_OPTSvariable just every bit earlier.
- Click on Run the Workflow and so Starting time to run the tests.
- Click on the Spock Tests job to see its output. If any of the tests would accept failed, the job would have ended in mistake. Fortunately, there were no errors:
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.022 due south - in DerivedSpec [INFO] Running HelloSpockSpec [INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 southward - in HelloSpockSpec [INFO] Running DataDrivenSpec [INFO] Tests run: 8, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.029 s - in DataDrivenSpec [INFO] Running StackWithThreeElementsSpec [INFO] Tests run: four, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.039 s - in StackWithThreeElementsSpec [INFO] Running EmptyStackSpec [INFO] Tests run: four, Failures: 0, Errors: 0, Skipped: 0, Fourth dimension elapsed: 0.017 s - in EmptyStackSpec [INFO] Running IncludeExcludeExtensionSpec [INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Fourth dimension elapsed: 0.006 s - in IncludeExcludeExtensionSpec [INFO] Running OrderedInteractionsSpec [INFO] Tests run: ane, Failures: 0, Errors: 0, Skipped: 0, Fourth dimension elapsed: 0.012 s - in OrderedInteractionsSpec [INFO] Running StackWithOneElementSpec [INFO] Tests run: four, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 due south - in StackWithOneElementSpec [INFO] Running UsingJUnitRulesSpec entering 'call up test name at runtime' leaving 'call up test proper name at runtime' [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.018 due south - in UsingJUnitRulesSpec [INFO] Running DatabaseDrivenSpec [INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Fourth dimension elapsed: 0.042 s - in DatabaseDrivenSpec [INFO] Running StepwiseExtensionSpec [INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.009 s - in StepwiseExtensionSpec [INFO] [INFO] Results: [INFO] [INFO] Tests run: 39, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.539 due south [INFO] Finished at: 2020-01-14T14:20:55Z [INFO] ------------------------------------------------------------------------ Proficient job! You at present accept an optimized CI pipeline for your Java project. You lot tin write your application with the confidence that the code is being tested on each stride of the way. Likewise, Semaphore comes with a slap-up Test Reports characteristic that gives you a full overview of your test suite.
You can add more tests or even combine multiple tests framework by calculation more jobs into the Tests block.
Once you lot've mastered Continuous Integration, you can become a step further and employ Semaphore to Continously Deploy your application.
Summary
In this tutorial, we've written several unit tests using Spock for both stubbing and mocking.
We've covered:
- How to download and ready upwards Spock via Maven,
- The advantages Spock brings when it comes to testing Coffee code
- Basic stubbing with the
>>operator, - Bones verification with the
N * mockedObject.method(arguments)syntax, - Advanced verification of arguments using Swell closure and the underscore character,
- Advanced dynamic manipulation of arguments, and,
- Advanced dynamic responses based on arguments.
- How to run your Spock tests continuously with Semaphore CI/CD.
Where to Become from Here
We've seen Spock'due south near important mocking features, but at that place are several more to explore:
- There are more than ways to restrict statement matchers,
- The number of verifications can also be described using Swell ranges,
- Stubs tin can be instructed to throw exceptions (for negative testing scenarios),
- You can also verify the event order as they happen in a unit test using multiple
and then:blocks, - You can stub multiple calls to the same method to return different results for each subsequent time, and,
- Spock likewise supports Spies, which is another avant-garde blazon of false objects.
If you have any questions and comments, feel costless to leave them in the section below. Also, feel free to share this tutorial with anyone you call up might benefit from it.
Read as well:
- Revving up Continuous Integration with Parallel Testing
- Testing a Java Spring Kick REST API with Karate
- Stubbing and Mocking with Mockito and JUnit
mcintyrehinge1963.blogspot.com
Source: https://semaphoreci.com/community/tutorials/stubbing-and-mocking-in-java-with-the-spock-testing-framework
0 Response to "Mockito Verify Returns True Even Though Method Wasn t Called Again"
Publicar un comentario