bean validation spring + hibernate annotion does not work - java

What am I doing wrong? The test does not work.
This is my Interface class:
#Validated
public interface ICustomerService
{
public List<Customer> findbyStr(
#NotEmpty(message = "{column.notvalid}")
#NotNull(message = "{column.notvalid}")
String column,
#NotEmpty(message = "{column.notvalid}")
#NotNull(message = "{value.notvalid}")
String value);
}
This is my Implementation class:
#Service("customerService")
#Scope(value = "singleton", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class CustomerService implements ICustomerService {
#Autowired
private IStorageDao<Customer> dao;
#Override
public List<Customer> findbyStr(String column, String value) {
return dao.findByString(Customer.class, column, value);
}
}
This is my unit-Test class:
JUNIT Test does not work.
#RunWith(SpringJUnit4ClassRunner.class)
public class CustomerTest extends BaseIntegrationTest {
#Autowired
private ICustomerService service;
#Autowired
public static Validator validator;
#Test
public void test_A6_CustomerFindByStrNull() {
List<Customer> result = service.findbyStr(null, null);
Set<ConstraintViolation<ICustomerService>> constraintViolations = validator
.validate(service);
assertEquals(0, constraintViolations.size());
assertEquals("Die angegebene E-Mail-Adresse ist fehlerhaft.",
constraintViolations.iterator().next().getMessage());
assertNotNull(result);
assertNotNull(result.get(1));
}
}

I'm pretty sure you cannot test ConstraintViolations when the annotations are on a method of an object since it should throw a MethodConstraintViolationException. You should try something like this :
#RunWith(SpringJUnit4ClassRunner.class)
public class CustomerTest extends BaseIntegrationTest {
#Autowired
private ICustomerService service;
#Test
public void test_A6_CustomerFindByStrNull() {
try {
List<Customer> result = service.findbyStr(null, null);
} catch (MethodConstraintViolationException ex) {
assertEquals("Die angegebene E-Mail-Adresse ist fehlerhaft.", ex.getConstraintViolations().iterator().next().getMessage());
}
fail("Exception expected");
}
}
You need to have the following Bean in your application-context.xml file :
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>

Related

How to update the data in Spring Boot MVC

I have the most common project on Spring Boot MVC. and I'm trying to write update data via PUT.
#RestController
#RequestMapping(CommentController.PATH)
public class CommentController {
public final static String PATH = "/comments";
#Autowired
private CommentService service;
#PutMapping("/{id}")
public Comment update(#RequestBody Comment comment, #PathVariable Long id) {
return service.update(id, comment);
}
}
#Service
public class CommentService {
#Autowired
private CommentRepository repository;
public Comment update(Long id, Comment entity) {
Optional<Comment> optionalEntityFromDB = repository.findById(id);
return optionalEntityFromDB
.map(e -> saveAndReturnSavedEntity(entity, e))
.orElseThrow(getNotFoundExceptionSupplier("Cannot update - not exist entity by id: " + id, OBJECT_NOT_FOUND));
}
private Comment saveAndReturnSavedEntity(Comment entity, Comment entityFromDB) {
entity.setId(entityFromDB.getId());
return repository.save(entity);
}
}
#Repository
public interface CommentRepository extends JpaRepository<Comment, Long> {
}
#Entity
public class Comment {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
#Column(name = "name")
protected String name;
}
then I write a test with the ability to check for updated data:
#SpringBootTest
#RunWith(SpringRunner.class)
#Transactional
// DBUnit config:
#DatabaseSetup("/comment.xml")
#TestExecutionListeners({
TransactionalTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class
})
public class CommentControllerTest {
private MockMvc mockMvc;
private static String route = PATH + "/{id}";
#Autowired
private CommentController commentController;
#Autowired
private CommentRepository commentRepository;
#PersistenceContext
private EntityManager entityManager;
#Before
public void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(commentController)
.build();
}
#Test
public void update_ShouldReturnCreated2() throws Exception {
int id = 1;
String name = "JohnNew";
Comment expectedComment = new Comment();
expectedComment.setName(name);
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(expectedComment);
this.mockMvc.perform(put(route, id)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(json))
.andDo(print());
entityManager.clear();
entityManager.flush();
Comment commentUpdated = commentRepository.findById(1L).get();
assertThat(commentUpdated.getName(), equalTo(name)); // not equals!
}
}
comment.xml:
<dataset>
<Comment id="1" name="John" />
</dataset>
but the problem is that the data is not updated.
If you enable the logging of Hibernat, then there is also no update request to the database.
What am I doing wrong?
You are missing off the #Transactional annotation from your CommentService. Whilst it can be better to add it at the per-method level, try adding it to class level to verify this fixes things:
#Service
#Transactional
public class CommentService {

Spring boot 2.1 test fails because of null property

I'm not an expert in Spring Boot. I have to write tests for my #RestController methods but I have a problem, which is, the #AutoWired ConfigurationProperties class is null when the test class executes the main controller. I found many posts about a similar issue here but they really don't solve this problem. The strange thing is that in the #PostConstruct method of the #RestController the property class is not null, it is null only in the #RequestMapping methods I'm trying to test.
This is my #SpringBootApplication class:
#SpringBootApplication
#ComponentScan
#EnableConfigurationProperties({MysqlProperties.class, CassandraProperties.class, GenericsProperties.class})
#EnableAutoConfiguration
public class REST {
public static void main(String[] args) {
SpringApplication.run(REST.class, args);
}
}
This is the #RestController:
#RestController
public class MainController {
#Autowired
private MysqlProperties mysqlProperties;
#PostConstruct
public void init() throws Exception {
//Here mysqlProperties is not null and I can get elements from it
}
#RequestMapping(value = "/online", method = RequestMethod.GET)
public #ResponseBody
String online(#RequestHeader(value = "email", required = true) String email, #RequestHeader(value = "password", required = true) String password) {
Utils.logInfo(logger, "/online endpoint");
//Here mysqlProperties is null
String sql = "SELECT * FROM " + mysqlProperties.getAddress() + " WHERE email= ?";
return new Return(Return.ERROR_MESSAGE, "Access denied, not superuser").toString();
}
This is the #ConfigurationProperties class:
#Configuration
#PropertySource("classpath:application.properties")
#ConfigurationProperties(prefix = "mysql")
public class MysqlProperties {
String address;
String database;
...
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
}
This is the test:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {REST.class})
#EnableConfigurationProperties({CassandraProperties.class, GenericsProperties.class, MysqlProperties.class})
#AutoConfigureMockMvc
public class MainControllerTest {
#Autowired
private MockMvc mvc;
#Autowired
private GenericsProperties genericsProperties;
#Before
public void init() {
try {
//mc.init();
mvc = MockMvcBuilders.standaloneSetup(new MainController()).build();
} catch (Exception ex) {
ex.printStackTrace();
Logger.getLogger(MainControllerTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Test
public void testOnline() throws Exception {
//Return returnObject = new Return(Return.DONE_MESSAGE, "System online");
Return returnObject = new Return(Return.ERROR_MESSAGE, "Access denied, not superuser");
this.mvc.perform(get("/online")
.header("email", genericsProperties.getSuperuser_email())
.header("password", genericsProperties.getSuperuser_password()))
//.contentType(APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().json(returnObject.toString()));
}
}
This is the package structure:
main
--java
----configurations
------MysqlProperties.java
----main
------MainController.java
----...
--resources
----application.properties
test
--java
----main
------MainControllerTest.java
The NullPointerException occurs in the MainController class at:
mysqlProperties.getAddress()
Any clue why it is not working? Thank you.
#Autowired MysqlProperties mysqlProperties is null bacause you created a new instance of MainController here:
mvc = MockMvcBuilders.standaloneSetup(new MainController()).build();
That instance will not be registered in the Spring context, therefore it will not be available for dependency injection.
You could read more about this issue here
You should use an autowired MainController in your MainControllerTest class.
#Autowired
private MainController mainController;

How to mock static access to spring-managed #Bean with Mockito?

I have a #Service bean that I need static access to:
#Service
public class MyBean implements InitializingBean {
private static MyBean instance;
#Override
public void afterPropertiesSet() throws Exception {
instance = this;
}
public static MyBean get() {
return instance;
}
public String someMethod(String param) {
return "some";
}
}
Usage:
#Service
public class OtherService {
public static void makeUse() {
MyBean myBean = MyBean.get();
}
}
Problem: when I write an integration junit test for OtherService that makes use of the stat MyBean access, the instance variable is always null.
#RunWith(SpringRunner.class)
#SpringBootTest
public class ITest {
#Autowired
private OtherService service;
#MockBean
private MyBean myBean;
#Before
public void mock() {
Mockito.when(myBean.someMethod(any()).thenReturn("testvalue");
}
#Test
public void test() {
service.makeUse(); //NullPointerException, as instance is null in MyBean
}
}
Question: how can I write an integration test when using such type of static access to a spring-managed bean?
If you want to influence the #Bean-creation, then use #Configuration
#Configuration
public class MyConfig {
#Bean
public MyBean myBean() {
return new MyBean;
}
#Bean
public OtherService otherService () {
return new OtherService(myBean());
}
}
Then mocking becomes really easy:
#RunWith(SpringRunner.class)
#SpringBootTest
public class ITest {
#MockBean
private MyBean myBean;
#Autowired
private OtherService service;
#Test
public void test() {
// service is initialised with myBean
...
}
}
When more control is needed, then you can choose the following approach. It provides sometimes more control than just a #MockBean. In your test you can easily mock a method just before calling it. This is my preferred way.
#Configuration
public class MyConfig {
...
#Bean
public MyBean getMyBean() {
return mock( MyBean.class);
}
#Bean
public OtherService otherService () {
return new OtherService( getMyBean());
}
}
In the application you can use #Autorwired to access it AND implement method overrule/mocking easily.
#RunWith(SpringRunner.class)
#SpringBootTest
public class AnotherTest {
#Autowired
private MyBean myBean;
#Autowired
private OtherService service;
#Test
public void test() {
when( myBean.method( a, b)).thenReturn( something);
service.doSomething( ....); // with myBean.method() overruled
}
}

Changing Spring XML configuration to #Configuration

My spring application is already configured via xml stye.I am trying to change it with #Configuration classes.
My app is used another project as maven library.I have a service, annotated with #Named and this service is used by another service in the library.
#Named("userDetailsService")
public class UserDetailsServiceImpl extends AbstractServiceImpl implements UserDetailsService {
#Inject
private UserService userService;
#Override
#Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return userService.getByUserName(username);
}
}
#Named("userService")
public class UserServiceImpl extends BaseDaoServiceImpl<User, UserDao> implements UserService {
#Inject
private AuthorityService authorityService;
#Inject
private UserAuthorityService userAuthorityService;
#Override
#Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public User getByUserName(String username) {
return dao.getByUserName(username);
}
#Override
public List<User> getUserWithHasAuthority(String authorityName) {
return dao.getUserWithHasAuthority(authorityName);
}
#Override
#Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public User insert(User user) {
user.setEnabled(true);
super.insert(user);
Authority authority = authorityService.getByName("ROLE_USER");
UserAuthority userAuthority = new UserAuthority();
userAuthority.setAuthority(authority);
userAuthority.setUser(user);
userAuthorityService.insert(userAuthority);
return user;
}
}
On my new #Configuration class
#Configuration
#ComponentScan(basePackages = {"com.mylibrary","com.myapp"})
#EnableAspectJAutoProxy(proxyTargetClass = true)
#EnableTransactionManagement
public class ServiceTestConfiguration {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
and this is my test method:
#Test
public void test() {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken("admin", "admin");
authenticationManager.authenticate(authenticationToken);
}
it gives null pointer exception on userService property that exist in userDetailsService.Both of them #Named.
Thnx for your help
Test classes :
#ContextConfiguration(classes = {ServiceTestConfiguration.class, DataSourceConfiguration.class, SecurityConfiguration.class})
#Transactional
public class AbstractTest {
}
#RunWith(SpringJUnit4ClassRunner.class)
public class ServiceTest extends AbstractTest {
#Inject
private AuthenticationManager authenticationManager;
#Test
public void test() {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken("admin", "admin");
authenticationManager.authenticate(authenticationToken);
}
}

Spring: Could not autowire. No beans of ... type found

I have problems with autowiring in Spring.
I have dao class for AccessLevel object like this:
Interface:
public interface AccessLevelDAO {
public AccessLevel select(Integer id);
}
It's implementation:
#Repository
public class AccessLevelDAOImpl implements AccessLevelDAO {
private SessionFactory sessionFactory;
#Autowired
public void AccessLevelDAO(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private Session currentSession() {
return sessionFactory.getCurrentSession();
}
#Override
#Transactional(propagation = Propagation.SUPPORTS,
isolation = Isolation.READ_UNCOMMITTED)
public AccessLevel select(Integer id) {
return (AccessLevel) currentSession().createCriteria(AccessLevel.class).add(Restrictions.idEq(id)).uniqueResult();
}
}
And service class which using this DAO class:
Interface:
public interface UserServices {
String getUserAccessLevel(String username);
AuthorizationResponseDTO authorize(String username, String password);
}
And implementation:
#Service
public class UserServicesImpl implements UserServices {
#Autowired private AccessLevelDAO accessLevelDAO;
#Autowired private UserDAO userDAO;
#Override
public String getUserAccessLevel(String username) {
User user = userDAO.select(username);
return accessLevelDAO.select(user.getAccessLevel()).getAccessLevel();
}
#Override
public AuthorizationResponseDTO authorize(String username, String password) {
return null;
}
}
When I'm trying to #Autowire accessLevelDAO and userDAO i get error message "Could not autowire. No beans of "AccessLevelDAO" type found".
Spring config includes component scan definition:
<context:annotation-config />
<context:component-scan base-package="com.core"/>

Categories