JHipster generates different types of tests for an application; some are optional and can be enabled while creating a new application, while some are always generated. The following are the different types of tests supported by JHipster and that we already talked about in Chapter 2, Getting Started with JHipster:
- Server-side unit tests: These are test cases for individual classes and methods and are done using JUnit.
- Server-side integration tests: These perform tests on the Spring components (REST controllers and services) making use of all of the layers behind them. It is done with Spring Test Framework and JUnit.
- Client-side unit tests: These are test cases for the client-side components and services and are done using the Jest framework.
- Client-side end-to-end tests: The end-to-end tests are written using the Protractor framework and they perform user behavior simulation on the GUI in a real browser. This is optional and can be enabled if required.
- Performance tests: JHipster can generate performance and load test specifications for the APIs using Gatling. This is optional and can be enabled if required.
- Behavior-driven development (BDD) tests: JHipster can generate BDD tests specifications using Cucumber. This is optional and can be enabled if required.
Before we dive into CI tools, let's first make sure that our tests are working, and there are no failed tests after the changes we made in the previous chapter. In an ideal world, where software development is done using practices such as TDD (short for test-driven development), writing and fixing tests is done along with the development of the code, and specifications are written before you develop the actual code.
You should try to follow this practice so that you write failing tests first for an expected result, and then develop code that will make the tests pass. Since our tests were autogenerated by JHipster, we can at least make sure that they are working when we make changes to the generated code.
Let's run our unit and integration tests to see whether any of them fail:
- Head over to your Terminal and navigate to the online-store folder first.
- Let's first run the server-side tests using Gradle:
> ./gradlew test integrationTest
Some of our tests failed with the following error trace:
com.mycompany.store.web.rest.OrderItemResourceIT > getAllOrderItems() FAILED
java.lang.AssertionError at OrderItemResourceIT.java:261
com.mycompany.store.web.rest.OrderItemResourceIT > getOrderItem() FAILED
java.lang.AssertionError at OrderItemResourceIT.java:277
com.mycompany.store.web.rest.InvoiceResourceIT > getInvoice() FAILED
java.lang.AssertionError at InvoiceResourceIT.java:341
com.mycompany.store.web.rest.InvoiceResourceIT > getAllInvoices() FAILED
java.lang.AssertionError at InvoiceResourceIT.java:321
com.mycompany.store.web.rest.ProductOrderResourceIT > getProductOrder() FAILED
java.lang.AssertionError at ProductOrderResourceIT.java:257
com.mycompany.store.web.rest.ProductOrderResourceIT > getAllProductOrders() FAILED
java.lang.AssertionError at ProductOrderResourceIT.java:241
com.mycompany.store.web.rest.ShipmentResourceIT > getAllShipments() FAILED
java.lang.AssertionError at ShipmentResourceIT.java:204
com.mycompany.store.web.rest.ShipmentResourceIT > getShipment() FAILED
java.lang.AssertionError at ShipmentResourceIT.java:220
194 tests completed, 8 failed
- These are expected to fail as we changed the Resource classes for these entities in the previous chapter to handle authorizations, and the failure means that it's working perfectly. Fortunately, it's not difficult to fix the tests using Spring. We can use the @WithMockUser annotation provided by the Spring test context to provide a mock user for our tests. Add the annotation with user details, as highlighted in the following code, to all of the failing test classes:
@SpringBootTest(classes = StoreApp.class)
@WithMockUser(username="admin", authorities={"ROLE_ADMIN"},
password = "admin")
public class InvoiceResourceIT {
...
}
- We are providing a mock user with the ADMIN role here. Add it to OrderItemResourceIT, ProductOrderResourceIT, and ShipmentResourceIT. Run the tests again and they should pass.
- Commit the changes made by running git commit -am "fix server-side tests with mockUser".
- Now, let's make sure our client-side Jest unit tests are working. Since we didn't make any logic changes on the client-side there shouldn't be any failures. Run the following command:
> npm test
- All tests should pass. Let's head over to src/test/javascript/spec/app/entities/product/product.component.spec.ts. We use the Jest framework for our tests. The existing test has the following structure. The beforeEach block sets up the Angular TestBed interface:
...
describe('Component Tests', () => {
describe('Product Management Component', () => {
...
beforeEach(() => {
TestBed.configureTestingModule({
...
})
.overrideTemplate(ProductComponent, '')
.compileComponents();
...
});
it('Should call load all on init', () => {
...
});
...
});
});
- Now, let's make sure our Protractor e2e tests are working. Run the following commands in two separate Terminals. Start the server first. Let's clear the database as well by running a clean task so that tests run on a fresh setup:
> ./gradlew clean bootRun
- Now, run the e2e tests:
> npm run e2e
-
We have two failed tests in the Product entity pages as we made changes there. Let's see how we can fix them:
- Let's open src/test/javascript/e2e/entities/product/product.spec.ts.
- The first failure is with the should create and save Products spec; if you look at the code, there is a call to a productComponentsPage.countDeleteButtons() method, and, if you inspect the method, it uses a query selector to find the delete buttons on the page. We need to update the query to match the new HTML structure. Find the following line:
deleteButtons = element.all(by.css('jhi-product div table .btn-danger'));
Change it to this:
deleteButtons = element.all(by.css('jhi-product div.list-group a .btn-danger'));
-
- The next failure is also due to the same reason and the preceding fix should be enough.
- If you look at the generated e2e tests, for example, src/test/javascript/e2e/entities/customer.spec.ts, you will see that some tests are commented out. These tests are commented out during generation if an entity has a required relationship field, as we would have to create a relationship first and set its value for the test to work, or if there are validations that JHipster cannot work out. Let's focus on only the Customer page test. Uncomment the test named should create and save Customers and change the describe function to describe.only on the file so that only this test file is executed:
describe.only('Customer e2e test', () => {
...
});
- First, uncomment the commented out imports. Now, execute npm run e2e and we should see one failing test. First, let's fix the email field by providing a valid email format:
it('should create and save Customers', () => {
...
customerUpdatePage.setEmailInput('[email protected]');
...
expect(customerUpdatePage.getEmailInput()).
toMatch('[email protected]');
...
});
- Run npm run e2e again and this time it should pass. But since we have a one-to-one relationship between the user and customer, the test will fail if we run it again; hence, we need to delete the row created after it. Let's uncomment the test case for the delete action. Uncomment the customerDeleteDialog variable at the beginning of the spec as well. Before running the tests again, we would have to manually clear the last entry created by the failed test to avoid unique constraint violations.
- Now, run npm run e2e twice to confirm this works. Do not forget to change describe.only to describe on the file so that all tests get executed. Congratulations! You have updated your first Protractor e2e tests.
- Similarly, fix the commented out e2e tests in other files under src/test/javascript/e2e/entities as well. This is a part of the next step's assignment. In some test cases, you would have to create an entity in another module to provide relationships.
Don't forget to commit your changes with git commit -am "fix client-side e2e tests".
Now, let's see what CI is all about.