Imagine I have the following simple example interface:
public interface UserDB {
void addUser(User user);
void updateUser(User user);
User getUser(String id);
void deleteUser(String id);
}
I want to write tests with Mockito to test the simple CRUD operations. I want to verify that things like:
Update/get/delete work only if the user was added before with 'add'
They fail if the user was deleted before with 'delete'.
Already created users cannot be created again
etc.
My idea is, that I need something like this:
UserDB udb = mock(UserDB.class);
when(udb.getUser("1")).thenThrow(new UserNotFoundException());
when(udb.addUser(new User("1"))).when(udb.getUser("1").thenReturn(new User("1"));
However, things like the last line are not proper Mockito syntax. How can I check verify different results, for different preconditions or different orders of methods called?
Doing it this way is a code smell. The fact that you want to write all this code to see if a "user cannot be added twice" is really basically just writing a new class, that has nothing to do with your database rules.
Here is one idea for something you could do instead; structure your validation rules as a Decorator on the database, and then test the decorator itself, with a mock "undecorated" database. For example:
public class ValidatingUserDB implements UserDB {
private UserDB delegate;
public ValidatingUserDB(UserDB delegate) {
this.delegate = delegate;
}
public void addUser(User user) {
User oldUser = delegate.get(user.getId());
if (oldUser != null) throw new IllegalArgumentException(
"User " + user.getId() + " already exists!";
delegate.addUser(user);
}
}
Then, you would write your tests like this:
#Test(expected=IllegalArgumentException.class)
public void testNoDuplicateUsers() {
User sampleUser = new User("1");
UserDB delegate = mock(UserDB.class);
when(delegate.getUser(any(User.class))).thenReturn(sampleUser);
UserDB db = new ValidatingUserDB(delegate);
db.addUser(sampleUser);
}
public void testAddingUser() {
User sampleUser = new User("1");
UserDB delegate = mock(UserDB.class);
UserDB db = new ValidatingUserDB(delegate);
db.addUser(sampleUser);
verify(delegate).getUser(sampleUser);
verify(delegate).addUser(sampleUser);
}
By separating the validation behavior from the CRUD behavior, you enable yourself to write tests in a way that doesn't involve you rewriting all these tests with super complicated answer rules and so forth.
Related
I working on writing tests for a crud application. I need to test the service and repository for Delete and Update statements. How would I go about mocking the repository for delete and update since they won't be returning data?
For example:
#Override
public void makeUserActive(long userId) {
try {
Optional<UserEntity> userEntityList = usersJpaRepository.findById(userId);
UserEntity userEntity = userEntityList.get();
userEntity.setIsActive(1);
usersJpaRepository.save(userEntity);
} catch (Exception e) {
logger.error("Cant make active user", e);
}
}
How do i test the service that mocks this repository and also the repository itself since it wont be returning a value
The question is what is the thing you want to be tested?
If you would like to test your repository you can achieve this by using Springs #DataJpaTest. see Integration Testing With #DataJpaTest
If you would like to test the logic inside your makeUserActive-Method you must make sure to mock your repository.
Assuming the service which contains your makeUserActive-Method looks something like this:
public class UserService{
private final UsersJpaRepository usersJpaRepository;
public UserService(UsersJpaRepository usersJpaRepository) {
this.usersJpaRepository = usersJpaRepository;
}
public void makeUserActive(long userId){
// your code from your question
}
}
You could write your Unit Test like this:
#Test
void makeUserActiveTest(){
UsersJpaRepository repository = new InMemoryUsersJpaRepository();
UserEntity user = new UserEntity();
user = repository.save(user);
UserService service = new UserService(repository);
service.makeUserActive(user.getId());
Optional<UserEntity> activatedUser = repository.findById(user.getId());
assertTrue(activatedUser.isPresent());
assertEquals(1, activatedUser.get().isActive());
}
The InMemoryUsersJpaRepository is a self written Mock which will store all data in an internal Map. The code could look something like this:
public class InMemoryUsersJpaRepository extends UsersJpaRepository {
private Map<Long, UserEntity> users = new HashMap<>();
private Long idCounter = 1L;
#Override
public UserEntity save(UserEntity user) {
if(user.getId() == null){
user.setId(idCounter);
idCounter++;
}
users.put(user.getId(), user);
return user;
}
#Override
public Optional<UserEntity> findById(long userId) {
return Optional.of(users.get(userId));
}
}
This way you will test the logic of your makeUserActive-Method which is currently to simply set the isActivated Flag on you UserEntity.
Also I would like to warn you about the answer of Mensur Qulami.
The Code in his answer will lead to a passing test but I'am pretty sure it does not test the thing you want to be tested.
You should always test the expected and observable behaviour of your method.
In your case this would be the isActivated Flag that should be 1.
The fact that your makeUserActive-Method calls the findById and save Method of the UsersJpaRepository is a mere implementation detail and the testing of those generally lead to brittle tests.
For the methods returning void, you can simply verify that they have been called. Here's an example, that mocks both an object returning method and void returning method.
#ExtendWith(MockitoExtension.class)
class ServiceTest {
#Mock
private Repository repository;
#InjectMocks
private Service service; // assume that this is your class
#Test
void testMakeUserActive() {
// given:
final UserEntity userEntity = new UserEntity();
// mocks:
when(repository.findById(1)).thenReturn(Optional.of(userEntity));
// when:
service.makeUserActive(1);
// then:
verify(repository).findById(1);
verify(repository).save(userEntity);
}
}
As a homework exercise (I'm a beginner) I had to write a Java program which accesses a database (PostgreSQL). The program can, e.g., insert new users, increment some fields etc. and I have methods such as: addUser(User t), deleteUser(User t) and so on.
I also have written test methods using junit5. For the tests I use a 'test' database, separate from the 'work' one. The coordinates to open the two databases (database name, password etc.) are stored in two files called config.properties and config.test.properties, which are selected at runtime.
What I have in place now is something along these lines, using a boolean flag variable:
public class UserDao {
public boolean isTestMode = false;
public Connection getConnection() {
if (this.isTestMode) {
input = cl.getResourceAsStream("config.test.properties");
} else {
input = cl.getResourceAsStream("config.properties");
}
...
}
}
In my test methods I then set the flag like this:
void testAddUser() {
UserDao dao = new UserDao();
dao.isTestMode = true;
...
}
In regular, non-test method I don't set isTestMode, which therefore stays to its default (false) value and config.properties is used.
My approach works, but my instructor told me it is bad practice to do things like this and I should change it, for example (he suggested) doing a dependency injection. I'm not too sure how to proceed.
I could make configFilename a class variable and add to the class UserDao a new constructor which accepts a filename, like this:
public class UserDao {
private String configFilename = "config.properties";
public UserDao() {
}
public UserDao(String filename) {
this();
this.configFilename = filename;
}
public Connection getConnection() {
input = cl.getResourceAsStream(this.configFilename);
...
}
}
Then in the test methods I use the new construtor UserDao("config.test.properties")
A (in my view a better) variant is to introduce a constructor which accepts a boolean isTestMode and sets configFilename accordingly (I don't need nor want the flexibility of specifying any filename in the constructor). But essentially this is the same as my original approach, which I was told to change. Also, there no dependency injection there... what is it best practice in such cases? Any suggestion would be welcome!
Passing parameter can be seen as a trivial dependency injection.
Concerning your java: when you set a default value for configFilename, you can see that as a convention that you use in your application.
Your class does not need that. And if you avoid this convention, you got immutability for free. For example, you can do :
public class UserDao {
private final String configFilename;
public UserDao(String filename) {
this.configFilename = filename;
}
public Connection getConnection() {
input = cl.getResourceAsStream(this.configFilename);
...
}
}
UserDao can be used by your test classes or your main classes the same way.
With your solution, you may deliver code that will never run in production (the branch where isTestMode is true), and that's not a good practice. This code could be seen as dead code in production.
In application use default constructor when creating an instance of UserDao, in junit pass name of file:
new UserDao("config.test.properties");
private final String configFilename;
public UserDao() {
this("config.properties");
}
public UserDao(String filename) {
this.configFilename = filename;
}
i'm developping a small buissness application and i need to know how to pass complex logic to indicate what Clients to fetch from the database
Here is my ClientDAO class :
public class ClientDAO {
public void save(Client clt) {
}
public Client find(int id) {
return null;
}
public void update(Client clt) {
}
public void delete(Client clt) {
}
}
This is a normal CRUD class, but if i need to fetch all client FROM date xx to yy, i need to add another find method overloaded?? and if i want to find all Client That have an age bettwen xx and yy i will another find function??
that don't seem a good design
i know what i'm doing is wrong, i want to know the right way to do it.
PS : i'm going to use JDBC without any ORM
When not using an ORM, creating multiple methods for querying the data is the right way to go. The purpose of the DAO is to totally isolate the rest of the application from the database access logic, meaning the DAO is the only class that knows the table and column names.
Now, for the advanced topic: If the application will need to query the table using a variety of criterias, creating a new method for each combination would be cumbersome, and having too many parameters on a single method wouldn't be right either.
For this kind of problem, the builder pattern is a good solution. Your DAO could implement a filter() method that returns a builder object, with good criteria methods and a final execute() method:
public class ClientDAO {
public static final class Filter {
Filter() {
// code not shown for brevity
}
public Filter withNameLike(String name) {
// code not shown for brevity
}
public Filter createdAfter(Date fromDate) {
// code not shown for brevity
}
public Filter createdBefore(Date fromDate) {
// code not shown for brevity
}
public List<Client> query() {
// code not shown for brevity
}
}
public static Filter filter() {
return new Filter();
}
}
It can then be used like:
List<Client> clients = ClientDAO.filter()
.withNameLike("%John%")
.createdAfter(fromDate)
.query();
I am working on a JavaEE project. All/Most classes i am working on reside on the data base. There fore all must support creating, editing and deleting a database entry.
I don't want to use any frameworks.I planed to execute the queries using the traditional prepared statements.
Currently I implemented it as follows
public interface Entity{
public boolean create(Entity e);//executes a query with the objects fields
public boolean change(Entity e);//executes a query to update fields of the entity
public boolean delete(Entity e);//deletes the entry
public ArrayList<Entity> getAll();//retrives all the entries in the database
}
Now my question
I'm i doing it right?
If a class inherites form a class that implements this interface how should it handel the methods? Should it override or call the super and add more code to handle more fields
Should i create another utility class to send the queries or is it ok if i add the database actions in the same class?
Appreciate in advance!
You are saying, that you are working on a Java EE project - so why don't use the APIs provided by it? There's a simple recommendation: Use JPA for it and only don't use prepared statements for CRUD operations of Java objects and don't reinvent an Entity which you already have at hand, together with an EntityManager doing all the operations you need on it.
What you are trying to implement is called a Data Access Object interface. It is in fact a well known and good practice, but judging from your interface name you want to use the CRUD methods directly whitin your entities and is not a good idea.
You should create an interface, say
public interface BookDAO{
public Book create(Book book);
public List<Book> read();
public Book update(Book book);
public Book delete(Book book);
}
with the CRUD methods. Then you can implement such interface depending on your database, say
class MySqlBookDAOImpl implements BookDAO{
private Connection conn;
private Connection getConnection(){
if(conn==null)
conn = mySqlConnectionPool.getConnection();
return conn;
};
#Override
public Book create(Book book){
Connection conn = getConnection();
String query = "INSERT... "
};
#Override
public List<Book> read(){
Connection conn = getConnection();
String query = "SELECT... "
};
#Override
public Book update(Book book){
Connection conn = getConnection();
String query = "UPDATE... "
};
#Override
public Book delete(Book book){
Connection conn = getConnection();
String query = "DELETE... "
};
}
and implement the abstract methods to communicate with the database using the correct database driver (depends also from your connection policies).
Regarding your other 2 questions:
When implementing a method from an interface you always ovveride it. You can't call a super method just because there is no super method. You call super only when you extend and override the method from the parent class.
The DAO should take care of sending the queries to the database and the DAO is going to create them within its methods.
Why are you so reluctant to use a framework or built in API? There are really good ones that can spare you a lot of work (like JPA).
You should distinguish entities and DAOs. Entities are the data, DAOs interact with the DB.
For example:
public interface Entity<K extends Serializable> {
K getId();
}
public interface Dao<K extends Serializable, E extends Entity<K>> {
E create(E entity);
E update(E entity);
E delete(E entity);
E get(K id);
List<E> getAll();
}
Then, implementations:
public class User implements Entity<Integer> {
private Integer id;
public User(Integer id) {
this.id = id;
}
#Override
public Integer getId() {
return id;
}
}
public class UserDao implements Dao<Integer, User> {
#Override
public User create(User entity) {
// build query
}
#Override
public User update(User entity) {
// build query
}
#Override
public User delete(User entity) {
// build query
}
#Override
public User get(Integer id) {
// build query
}
#Override
public List<User> getAll() {
// build query
}
}
This can be improved by having a BaseDao abstract class for example, since DAOs will have common code for sure.
Actually I can see you are missing a very basic operation wchich is acceessing objects:
public boolean read(Entity e);
You should also reconsider your class name to have a more relevant one (what this class is intended to do) since naming it as Entity gives the allure of a bean entity not a data access interface layer. Something like CommonDao:
public interface CommonDao {
//...
}
This class can be extended following your Entity type.
You may also need to revise your method signatures, e.g. deleting an entity should only need its identifier.
Update your class also to use Java Generics which will let you gain in reusability and make your class accept any entity type:
public interface CommonDao<T> {
T create(T entity);
//...
}
I highly recommand #sp00m solution.
What's the recommended way to handle user management in Play! Framework?
This is my setup:
UserAwareControllerBase as a base class for controllers
The main view template includes a login/logout button
custom Security class extending Secure.Security, and controllers that only allow signed-in users are annotated with #With(Secure.class)
(I haven't implemented a real password/login system yet, just entering the correct email suffices to login. TBD)
The setup is nice because Controllers don't need to bother writing user management code, and can easily get the signed-in user by calling getUser(). However, I'm already starting to feel the limitations of this setup. I'm getting a convoluted inheritance hierarchy, and am facing a problem if I want to inherit from the CRUD class.
What's the best practice for handling user authentication/authorization in Play! without repeating code?
UserAwareControllerBase.java
public abstract class UserAwareControllerBase extends Controller {
protected final static UserRepository userRepo = new UserRepository();
#Before
static void setConnectedUser() {
if(Security.isConnected()) {
User user = userRepo.findByEmail(Security.connected());
renderArgs.put("user", user);
}
}
static User getUser() {
return renderArgs.get("user", User.class);
}
}
template.html
<div id='header'>
...
#{if user}
Log out (${user.email})
#{/if}
#{else}
Log in
#{/else}
</div>
Security.java
public class Security extends Secure.Security {
protected final static UserRepository userRepo = new UserRepository();
static boolean authenticate(String username, String password) {
User user = userRepo.findByEmail(username);
return user != null;
}
public static void onDisconnected() {
Application.index();
}
}
If you want to share code between controllers, prefer using the #With annotation rather than using inheritance.
For user management, I am used to put some rights in the session in the onAuthenticated method like this
static void onAuthenticated() {
session.put(Const.MY_RIGHT, true);
}
And then my check method is
static boolean check(String profile) {
return Boolean.parseBoolean(session.get(profile));
}
With this I can use the #check annotation to check user rights. In the onAuthenticated method you can do whatever you want to map complex rights managements into simple constants.