I had a Springframework-enabled JUnit test that I needed to run multiple times. I thought there used to be a JUnit annotation, but I couldn’t find it. I found and used the Spring @Repeat annotation.
package com.this.and.that; import https://javaninja.net/files/tag/org.junit.test; import https://javaninja.net/files/tag/org.junit.runner.runwith; import https://javaninja.net/files/tag/org.springframework.test.annotation.repeat; import https://javaninja.net/files/tag/org.springframework.test.context.contextconfiguration; import https://javaninja.net/files/tag/org.springframework.test.context.testexecutionlisteners; import https://javaninja.net/files/tag/org.springframework.test.context.junit4.springjunit4classrunner; import https://javaninja.net/files/tag/org.springframework.test.context.support.dependencyinjectiontestexecutionlistener; import https://javaninja.net/files/tag/java.util.concurrent.linkedblockingqueue; import https://javaninja.net/files/tag/static org.junit.assert.assertequals; import https://javaninja.net/files/tag/static org.junit.assert.assertnotnull; @RunWith(SpringJUnit4ClassRunner.class) @TestExecutionListeners(DependencyInjectionTestExecutionListener.class) @ContextConfiguration public class TestCardSet { @Repeat(10) @Test public void testGetShuffledCardQueue() throws Exception { LinkedBlockingQueue<Card> cards = CardSet.getShuffledCardQueue(); assertNotNull(cards); assertEquals(52, cards.size()); } }
I used to set breakpoints to verify that the test was being ran multiple times. The Spring @Repeat annotation removed the need for this by adding logging.
2014-12-02 09:41:05,499 INFO o.s.beans.factory.xml.XmlBeanDefinitionReader:315 - Loading XML bean definitions from class path resource [com/iteam/poker/server/model/game/cards/TestCardSet-context.xml] 2014-12-02 09:41:05,815 INFO o.s.context.support.GenericApplicationContext:510 - Refreshing org.springframework.context.support.GenericApplicationContext@4c6cea8a: startup date [Tue Dec 02 09:41:05 EST 2014]; root of context hierarchy 2014-12-02 09:41:05,866 INFO o.s.b.factory.support.DefaultListableBeanFactory:598 - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6f7503eb: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy 2014-12-02 09:41:05,886 INFO o.s.test.context.junit4.statements.SpringRepeat:69 - Repetition 1 of test TestCardSet#testGetShuffledCardQueue() 2014-12-02 09:41:05,898 INFO c.i.poker.server.shuffle.SecureShuffleAlgorithm:26 - Cards shuffle algorithm seed has been initialized. 2014-12-02 09:41:05,899 INFO o.s.test.context.junit4.statements.SpringRepeat:69 - Repetition 2 of test TestCardSet#testGetShuffledCardQueue() 2014-12-02 09:41:05,900 INFO o.s.test.context.junit4.statements.SpringRepeat:69 - Repetition 3 of test TestCardSet#testGetShuffledCardQueue() 2014-12-02 09:41:05,901 INFO o.s.test.context.junit4.statements.SpringRepeat:69 - Repetition 4 of test TestCardSet#testGetShuffledCardQueue() 2014-12-02 09:41:05,902 INFO o.s.test.context.junit4.statements.SpringRepeat:69 - Repetition 5 of test TestCardSet#testGetShuffledCardQueue() 2014-12-02 09:41:05,903 INFO o.s.test.context.junit4.statements.SpringRepeat:69 - Repetition 6 of test TestCardSet#testGetShuffledCardQueue() 2014-12-02 09:41:05,903 INFO o.s.test.context.junit4.statements.SpringRepeat:69 - Repetition 7 of test TestCardSet#testGetShuffledCardQueue() 2014-12-02 09:41:05,904 INFO o.s.test.context.junit4.statements.SpringRepeat:69 - Repetition 8 of test TestCardSet#testGetShuffledCardQueue() 2014-12-02 09:41:05,905 INFO o.s.test.context.junit4.statements.SpringRepeat:69 - Repetition 9 of test TestCardSet#testGetShuffledCardQueue() 2014-12-02 09:41:05,906 INFO o.s.test.context.junit4.statements.SpringRepeat:69 - Repetition 10 of test TestCardSet#testGetShuffledCardQueue() Process finished with exit code 0
sheltonn December 2nd, 2014
Posted In: JUnit, Spring, Test Driven Development, Unit Tests
Tags: Java, JUnit, Spring, SpringFramework, TDD, Test Driven Development
I have a normal Springframework-enabled project arranged as a Maven project. There were already JUnit tests in the project, along with the requisite Spring configuration.
I needed to add Cucumber tests to the project. I started by adding a cucumber directory to my src/test/java and src/test/resources directories.
I added my feature file in ../src/test/resources/com/cdi/igs/adapter/cucumber/features/Login.feature.
Feature: Login @2014w34 @US2422 Scenario Outline: A lite registered player with email verified should be able submit username and password in the poker client. After submission player will see a system message to complete registration and will get re-direct to complete registration step 2 in IGP Given my username is "<UserName>" And my password is "<Password>" And my registration status is "lit" And my email verification status is verified as "<email verification status>" When I provide my credentials Then I should receive the following Poker status "<login result>" Examples: | UserName | Password | login result |email verification status| | player1 | Password#1 | AUTH_FAILED_LIT | 1 | @2014w34 @US2326 Scenario Outline: A fully registered user should be able to login into the existing poker client. User in examples must be a fully registered user. 0 = SUCCESS, 1 = AUTH_FAILED Given my username is "<UserName>" And my password is "<Password>" And my registration status is "ful" When I provide my credentials Then I should receive the following Poker status "<Login Result>" And I should receive the following demographic data "<First Name>" "<Last Name>" "<Address1>" "<Address2>" "<City>" "<State>" "<Zip>" And I should have a third party authentication token Examples: | UserName | Password | Login Result | First Name | Last Name | Address1 | Address2 | City | State | Zip | | player2 | Password#1 | SUCCESS | Player | Test | 1505 Test Address | Apt 100 | New York | NY | 80000 | @2014w34 @US2538 Scenario Outline: A lite registered user whose email is not verified will be shown the relevant messaging, and they will be requested to become fully registered Given my username is "<UserName>" And my password is "<Password>" And my registration status is "lit" And my email verification status is verified as "<email verification status>" When I provide my credentials Then I should receive the following Poker status "<login result>" Examples: | UserName | Password |email verification status | login result | | 8player | Password!#01 |0 | AUTH_FAILED_LIT_NO_EMAIL | @2014w36 @US2639 Scenario Outline: Player with existing Password locked status with IGP authentication, cannot login to poker client. Given my username is "<UserName>" And my password is "<Password>" And my person status is "psl" When I provide my credentials Then I should receive the following Poker status "<login result>" Examples: | UserName | Password | login result | | gawky1 | Password#1 | LOCKED_PASSWORD_RESET | @2014w36 @US2629 Scenario Outline: Player with existing Reset locked status with IGP authentication, cannot login to poker client. Given my username is "<UserName>" And my password is "<Password>" And my person status is "rsl" When I provide my credentials Then I should receive the following Poker status "<login result>" Examples: | UserName | Password | login result | | gawky | Password#1 | LOCKED_CUSTOMER_SERVICE_RESET |
I added my steps file that defines the implementations in …/src/test/java/com/cdi/igs/adapter/cucumber/steps/LoginSteps.java.
package com.cdi.igs.adapter.cucumber.steps; import https://javaninja.net/files/tag/com.cdi.igs.adapter.login.loginrequest; import https://javaninja.net/files/tag/com.cdi.igs.adapter.login.loginresponse; import https://javaninja.net/files/tag/com.cdi.igs.adapter.poker.login.pokerloginservice; import https://javaninja.net/files/tag/com.cdi.igs.dao.person.person; import https://javaninja.net/files/tag/com.cdi.igs.dao.person.personRepository; import https://javaninja.net/files/tag/com.cdi.igs.dao.personhasverifiableitem.personhasverifiableitem; import https://javaninja.net/files/tag/com.cdi.igs.dao.personhasverifiableitem.personhasverifiableitemRepository; import https://javaninja.net/files/tag/cucumber.api.java.en.and; import https://javaninja.net/files/tag/cucumber.api.java.en.given; import https://javaninja.net/files/tag/cucumber.api.java.en.then; import https://javaninja.net/files/tag/cucumber.api.java.en.when; import https://javaninja.net/files/tag/org.apache.commons.lang3.stringutils; import https://javaninja.net/files/tag/org.springframework.beans.factory.annotation.autowired; import https://javaninja.net/files/tag/org.springframework.test.context.contextconfiguration; import https://javaninja.net/files/tag/java.util.list; import https://javaninja.net/files/tag/static org.junit.assert.assertequals; import https://javaninja.net/files/tag/static org.junit.assert.assertnotnull; /** * Login cucumber steps. * @author norris.shelton */ @ContextConfiguration("classpath:TestCucumber-context.xml") public class LoginSteps { @Autowired private PersonRepository personRepository; @Autowired private PersonHasVerifiableItemRepository personHasVerifiableItemRepository; @Autowired private PokerLoginService pokerLoginService; private String username; private String password; private Person person; LoginResponse loginResponse; @Given("^my username is "([^"]*)"$") public void my_username_is(String username) throws Throwable { this.username = username; } @And("^my password is "([^"]*)"$") public void my_password_is(String password) throws Throwable { this.password = password; } @Given("^my registration status is "(.*?)"$") public void my_registration_status_is(String registrationStatus) throws Throwable { person = personRepository.findByUserName(username); assertEquals(registrationStatus, person.getIdRegistrationStatus()); } @Then("^I should receive the following Poker status "(.*?)"$") public void i_should_receive_the_following_Poker_status(String responseStatus) throws Throwable { assertEquals(responseStatus, loginResponse.getStatus().value()); } @Given("^my email verification status is verified as "(.*?)"$") public void my_email_verification_status_is_verified_as(String emailVerificationStatus) throws Throwable { List<PersonHasVerifiableItem> personHasVerifiableItemList = personHasVerifiableItemRepository.findByIdPersonAndIdVerifiableItemOrderByTimeStampDesc(person.getIdPerson(), "ema"); if (!personHasVerifiableItemList.isEmpty()) { for (PersonHasVerifiableItem emailVerifiableItem : personHasVerifiableItemList) { if (emailVerifiableItem.isSuccess()) { assertEquals(person.getIdPerson(),emailVerifiableItem.getIdPerson()); break; } } } } @Given("^my person status is "(.*?)"$") public void my_person_status_is(String personStatus) throws Throwable { person = personRepository.findByUserName(username); assertEquals(personStatus, person.getIdPersonStatus()); } @When("^I provide my credentials$") public void I_provide_my_credentials() throws Throwable { LoginRequest loginRequest = new LoginRequest(); loginRequest.setUserId(username); loginRequest.setPassword(password); loginResponse = pokerLoginService.login(loginRequest); } @And( "^I should receive the following demographic data "([^"]*)" "([^"]*)" "([^"]*)" "([^"]*)" "" + "([^"]*)" "([^"]*)" "([^"]*)"$") public void I_should_receive_the_following_demographic_data(String firstName, String lastName, String address1, String address2, String city, String state, String zip) throws Throwable { assertEquals(firstName, StringUtils.trimToEmpty(loginResponse.getFirstName())); assertEquals(lastName, StringUtils.trimToEmpty(loginResponse.getLastName())); assertEquals(address1, StringUtils.trimToEmpty(loginResponse.getStreetAddress1())); assertEquals(address2, StringUtils.trimToEmpty(loginResponse.getStreetAddress2())); assertEquals(city, StringUtils.trimToEmpty(loginResponse.getCity())); assertEquals(state, StringUtils.trimToEmpty(loginResponse.getIdState())); assertEquals(zip, StringUtils.trimToEmpty(loginResponse.getZipCode())); } @And("^I should have a third party authentication token$") public void I_should_have_a_third_party_authentication_token() throws Throwable { assertNotNull(StringUtils.trimToNull(loginResponse.getThirdPartyAuthenticationToken())); } }
Now that I have the feature and the steps created, I added in the Cucumber runner in
…/src/test/java/com/cdi/igs/adapter/cucumber/TestCucumber.java. Notice the glue property of @CucumberOptions. That defines directories to scan.
package com.cdi.igs.adapter.cucumber;</code> import https://javaninja.net/files/tag/cucumber.api.cucumberoptions; import https://javaninja.net/files/tag/cucumber.api.junit.cucumber; import https://javaninja.net/files/tag/org.junit.runner.runwith; /** * JUnit test class for cucumber. * @author norris.shelton */ @RunWith(Cucumber.class) @CucumberOptions( tags = {}, glue = {"com.cdi.igs.adapter.cucumber", "cucumber.api.spring"}) public class TestCucumber { }
In the top of the LoginSteps class, there was a ContextConfiguration annotation.
@ContextConfiguration("classpath:TestCucumber-context.xml")
That Spring context config file is located in …/src/test/resources/TestCucumber-context.xml and thee contents of that are as follows:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <import rhttps://javaninja.net/files/tag/esource="classpath*:TestAdapter-context.xml"/> </beans>
It merely says use whatever Spring configuration has already been defined for the rest of the project.
sheltonn November 20th, 2014
Posted In: Cucumber, Integration Tests, Java, JUnit, Spring, TDD, Test Driven Development, Unit Tests
Tags: Cucumber, Integration Tests, Java, JUnit, Spring, Spring Test, TDD, Test, Test Driven Development, Unit Tests
How do you mock a Springframework security principal for testing spring MVC controllers?
The last step should not be needed because MockMVC has a method to set the principal (line 16). However, we had an annotation that used the security principal to retrieve the username that was then used to retrieve another object. We couldn’t find the value there. We set the spring security authentication manually via the spring security context (line 19).
public class TestActivityController { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void setup() { mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); } @Test public void testInitialDisplay() throws Exception { User user = new User("screen011","", AuthorityUtils.createAuthorityList("ROLE_PATRON")); TestingAuthenticationToken testingAuthenticationToken = new TestingAuthenticationToken(user,null); SecurityContextHolder.getContext().setAuthentication(testingAuthenticationToken); mockMvc.perform(post("/activity/initial") //.principal(testingAuthenticationToken)) .andExpect(status().isOk()) .andDo(print()); } }
sheltonn February 27th, 2014
Posted In: Java, MockMVC, Spring, Spring MVC, Spring Security
Tags: Integration Tests, Java, JUnit, mock, mockito, mockmvc, MVC, Spring, spring mvc, Spring Security, Spring Test, TDD, Test, Test Driven Development, Unit Tests
I have a Springframework integrated Junit test. I had seen annotating a Junit test class with @Test(expected = Exception.class) to test for exceptions before. In this case, we needed to test for Exception and the message was made the difference. This can be accomplished by @Rule
@Rule public ExpectedException expectedEx = ExpectedException.none(); @Test(expected = Exception.class) public void testAddNegativeTransaction() throws Exception { expectedEx.expect(Exception.class); expectedEx.expectMessage("Cannot withdraw more than available balance."); transactionService.addNegativeTransaction(new TransactionRequest("1", "acw", 10, 2000.00)); }
sheltonn February 5th, 2014
Posted In: Integration Tests, Java, JUnit, Test Driven Development
Tags: exceptions, expected exceptions, Integration Tests, Java, JUnit, Spring, Spring Test, TDD, Test, Test Driven Development, unit test