Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am trying to test a class which is using dao. In my test class I have mocked the DAO and inject the mock into an instance of the class that I test. I am trying to make a fake object of the DAO class.
#RunWith(MockitoJUnitRunner.class)
public class UserManagerTest {
#Mock
private UserManagerDao umDao;
#InjectMocks
private UserManager um = new UserManager();
#Before
public void initializeMockito() {
MockitoAnnotations.initMocks(this);
}
public void testGetUserId() {
}
This here are the methods from UserManager.class and Dao class
userManager.class
public long getUserId(String email) throws Exception {
String[] partsOfMail = email.split("#");
return umDao.getUserId(partsOfMail[0], partsOfMail[1]);
}
Dao class
public long getUserId(String userName, String domain) throws Exception {
String sql = msa.getMessage("sql.select.user_id");
Object[] params = new Object[] { userName, domain };
List<Long> result = getJdbcTemplate().queryForList(sql, params, Long.class);
if (result.size() > 0) {
return result.get(0);
}
return 0;
}
See comments:
#RunWith(MockitoJUnitRunner.class)
public class UserManagerTest {
#Mock
private UserManagerDao umDao; // a mock object should present here
/* #InjectMocks should be able to create an instance
with mocks injected for you - you don't need to create it
yourself */
#InjectMocks
private UserManager um; // = new UserManager();
/* Not required as you're using the MockitoJUnitRunner
#Before
public void initializeMockito() {
MockitoAnnotations.initMocks(this);
} */
// Add test annotation (assuming JUnit4 as you're not extending TestCase)
#Test
public void testGetUserId() {
// Both these fields should not be null
Assert.assertNotNull(umDao);
Assert.assertNotNull(um);
}
For more information take a look at MockitoJUnitRunner and InjectMocks documentation.
Mockito's documentation, which included many examples, can be found here.
What is your question? If you are asking how to mock some method in the DAO, this is a simple example.
#Test
public void testGetUserId() {
when(umDao.getUserId(<PARS>)).thenReturn(1L);
assertThat(um.getUserId(<PAR>)).isEqualTo(1L);
}
Related
Is it possible to write unit test using Junit 5 mockito for retryable annotations?
I am having a service interface which has only one method, which downloads the file from remote url
#service
interface downloadpdf{
#Retryable(value = { FileNotFoundException.class, HttpClientErrorException.class }, maxAttempts = 5, backoff = #Backoff(delay = 1000))
public string downloadpdffile(string remoteurl, string pdfname);
}
I have tried referring sites and found using Spring4JunitRunner implementation to test retry. Got confused with implementation. Is it possible to write unit test using Junit 5 mockito for retryable annotations?. Could you please elaborate on the solution here?
You need to use #SpringJUnitConfig (which is the equivalent of the JUnit4 runner). Or #SpringBootTest as you are using Boot.
#Retryable only works with beans managed by Spring - it wraps the bean in a proxy.
#SpringBootApplication
#EnableRetry
public class So71849077Application {
public static void main(String[] args) {
SpringApplication.run(So71849077Application.class, args);
}
}
#Component
class RetryableClass {
private SomeService service;
void setService(SomeService service) {
this.service = service;
}
#Retryable
void retryableMethod(String in) {
service.callme();
throw new RuntimeException();
}
#Recover
void recover(Exception ex, String in) {
service.failed();
}
}
interface SomeService {
void callme();
void failed();
}
#SpringBootTest
class So71849077ApplicationTests {
#MockBean
SomeService service;
#Test
void testRetry(#Autowired RetryableClass retryable) {
SomeService service = mock(SomeService.class);
retryable.setService(service);
retryable.retryableMethod("foo");
verify(service, times(3)).callme();
verify(service).failed();
}
}
I was also trying to implement this using Junit5.
Tried various options but that didn't help. Then after googling for few hours, got the following link and it helped to succeed.
https://doctorjw.wordpress.com/2022/04/29/spring-testing-a-single-bean-in-junit-5-springextension/
Reference code below, for detailed explanation, please refer the blog.
#Component
public class MyClass {
private ObjectMapper objectMapper;
private RestTemplate restTemplate;
#Value("${testValue:5}")
private int value;
#Retryable(....)
public void doStuff() throws SomeException {
...
}
}
What I’ve discovered is, if I declare my test class this way:
#ExtendWith( SpringExtension.class )
#Import( { MyClass.class, ObjectMapper.class } )
#EnableRetry
public class MyClassTest {
#Autowired
private MyClass myClass;
#MockBean
private RestTemplate restTemplate;
#Autowired
private ObjectMapper objectMapper;
#BeforeEach
public void setup() {
// If we are going to jack with the object configuration,
// we need to do so on the actual object, not the Spring proxy.
// So, use AopTestUtils to get around the proxy to the actual obj.
TestingUtils.setFieldValue( AopTestUtils.getTargetObject( myClass ), "value", 10 );
}
}
You will notice the inclusion of 1 other class, TestingUtils.class. This class looks like:
public class TestingUtils {
public static void setFieldValue( Object object, String fieldName, Object value ) {
Field field = ReflectionUtils.findField( object.getClass(), fieldName );
ReflectionUtils.makeAccessible( field );
ReflectionUtils.setField( field, object, value );
}
}
All credits goes to the author of the blog.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed last year.
Improve this question
I have the following code snippets in my spring boot application:
#Service
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
public UserServiceImpl(UserRepository ...) {...}
#Override
public void saveOrUpdateUser(UserDAO user) {
userRepository.save(user);
}
}
Test case class:
class UserServiceImplUnitTest {
private UserRepository userRepository = mock(UserRepository.class);
private UserService userService;
#BeforeEach
void setup() {
userService = new UserServiceImpl(userRepository);
}
}
I am using mockito to write my test cases. However, for this void method should i write test case(s)? If yes, how can i write it?
Yes. You should mainly focus on whether UserServiceImpl interacts with UserRepository in an expected way such as the things like if it invokes the correct method on the UserRepository with the correct arguments etc.
By using Mockito to mock the UserRepository , you may end up with a test something like as follows :
#ExtendWith(MockitoExtension.class)
public class UserServiceImplUnitTest {
#Mock
UserRepository userRepository ;
UserService userService;
#BeforeEach
void setup() {
userService = new UserServiceImpl(userRepository);
}
#Test
public void testSaveOrUpdateUser(){
UserDAO user = createDummyUser();
userService.saveOrUpdateUser(user);
verify(userRepository).save(same(user));
}
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I have some configuration property defined as
#Data
#ConfigurationProperties(prefix = RedisClientConfigProperties.CONFIG_PROP_NAME)
public class RedisClientConfigProperties {
public static final String CONFIG_PROP_NAME = "dao.redis";
private int database = 0;
private String host = "127.0.0.1";
private int port = 6379;
private boolean enabled = false;
}
and the following java classes:
public interface IDao {
Object get(UUID id);
void put(UUID id, Object item);
}
public class NoOpDao implements IDao {
#Override
public Object get(UUID id) {
return new Object();
}
#Override
public void put(UUID id, Object item) {
// no-op
}
}
public class RedisDao implements IDao {
#Autowired
private RedisClient client;
#Override
public Object get(UUID id) {
return client.get(id);
}
#Override
public void put(UUID id, Object item) {
client.put(id, item);
}
}
What I want is to be able to autowire an IDao object into another bean, and the implementation is decided at run time based on the RedisClientConfigProperties#enabled field. In Guice, i can do something like the following in a module:
class DaoModule extends PrivateModule {
private final RedisClientConfigProperties configProps;
#Inject
public DaoModule(RedisClientConfigProperties configProps) {
this.configProps = configProps;
}
#Override
protected void configure() {
if (configProps.isEnabled()) {
bind(IDao.class).to(RedisDao.class);
} else {
bind(IDao.class).to(NoOpDao.class);
}
}
}
In Spring, it is a little unclear of how to go about doing this. I have found a few different ways to do it, but I'm not sure what is the "Spring way" to do it:
Use a #Configuration class with an #Bean method that returns IDao with conditional logic inside the method
#Bean
public IDao getDao(RedisClientConfigProperties config) {
if (config.isEnabled()) return new RedisDao();
else return new NoOpDao;
}
Use the service locator pattern to create a factory which will return the bean you want
annotate the implementations with #ConditionalOnProperty annotations
I'm curious about which of these ways is recommended as I have some reservations about each of them:
I would rather not have to manually instantiate the beans and have Springs IOC deal with instantiating the beans as necessary
This still creates al of the interface implementation beans and requires any consumer of the bean to know what bean they are asking for
Potentially error prone given that it doesn't use the Config properties object, but instead looks directly in your config properties files.
Out of these three solutions, I think I prefer #1 but would love feedback / recommendations.
Your code seems that its per application, so what I recommend is have all of your properties in the configuration path, and not in a RedisClientConfigProperties.
keeping your class but modify it like so:
RedisClientConfig.java
#Data
#ConfigurationProperties(prefix = "dao.redis")
public class RedisClientConfigProperties {
private int database;
private String host;
private int port;
private boolean enabled;
// public getters and setters
.
.
}
And in your configuration file:
application.yml
dao:
redis:
enabled: true
database: 0
host: 127.0.0.1
port: 6379
And have your dao be only injected in the context based on the property
You can have it check if property is defined if you only use prefix to avoid passing boolean
RedisDao.java
#Component
#Primary
#ConditionalOnProperty(prefix = "dao.redis", name = "enabled", havingValue = "true")
public class RedisDao implements IDao {
.
.
.
}
This way you will have have your NoOpDao be always injected,
Unless the dao.redis.enabled is true, then the Redis will override the NoOpDao implementation because its annotated with #Primary.
I got 2 modules User and Email, both of them have 1 entry point which is a facade, rest is package scoped. The configuration is done in 2 classes
#Configuration
class UserConfiguration {
#Bean
UserFacade userFacade(UserRepository repository, EmailFacade emailFacade) {
return new UserFacade(repository, emailFacade);
}
}
#Configuration
class EmailConfiguration {
#Bean
EmailFacade emailFacade(EmailSender emailSender) {
return new EmailFacade(emailSender);
}
}
Now, I want to write tests that don't require Spring to start. I implemented a simple InMemoryRepository to make this happen
#RunWith(MockitoJUnitRunner.class)
public class RegisterUserTest {
#Mock
private EmailFacade emailFacade = new EmailFacade(new FakeEmailSender());
#InjectMocks
private UserFacade userFacade = new UserConfiguration().userFacade(new InMemoryUserRepository(), emailFacade);
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
}
I need some fake objects to instantiate EmailFacade so I wrote fake implementation
public class FakeEmailSender implements EmailSender {
#Override
public void sendEmail(EmailMessage emailMessage) throws RuntimeException {
}
}
In that scenario, I'm testing User domain, so I want to mock Email anyways.
I wrote a test to check if it works
#Test
public void shouldReturnSendingFailed() {
Mockito.when(emailFacade.sendUserVerificationEmail(Mockito.any())).thenReturn(Either.left(EmailError.SENDING_FAILED));
assertThat(userFacade.registerNewUser(RegisterUserDto.builder()
.username(USERNAME_4)
.email(VALID_EMAIL)
.password(VALID_PASSWORD).build()).getLeft(), is(EmailError.SENDING_FAILED));
}
But it isn't... after running this test I got
java.util.NoSuchElementException: getLeft() on Right
edit#
regiserNewUser() method
Either<DomainError, SuccessMessage> register(RegisterUserDto registerUserDto) {
if(userRepository.findUser(registerUserDto.getUsername()).isPresent())
return Either.left(UserError.USERNAME_ALREADY_EXISTS);
var userCreationResult = User.createUser(registerUserDto);
var savedUser = userCreationResult.map(this::saveUser);
var emailDto = savedUser.map(this::createVerificationEmail);
return emailDto.isRight() ? emailFacade.sendUserVerificationEmail(emailDto.get())
: Either.left(emailDto.getLeft());
}
Edit2#
With following test configuration
#RunWith(MockitoJUnitRunner.class)
public class RegisterUserTest {
#Mock
private EmailFacade emailFacade;
#InjectMocks
private UserFacade userFacade = new UserConfiguration().userFacade(new InMemoryUserRepository(), emailFacade);
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
}
I got nullpointer here, last line of registerNewUser().
Try running this code
#RunWith(MockitoJUnitRunner.class)
public class RegisterUserTest {
#Mock
private EmailFacade emailFacade;
private UserFacade userFacade;
#Before
public void setUp() {
userFacade = new UserConfiguration().userFacade(new InMemoryUserRepository(), emailFacade);
}
}
There are a few issues with your code:
You initialize your mocks twice. You don’t need to call initMocks in the setUp method if you are using Mockito runner
You are trying to inject mocks to already initialized object. But the field you are trying to inject is also passed to the constructor. Please read #InjectMocks doc, to check the strategies used to inject the mocks:
constructor (not used here, already initialized object)
setter (do you have one?)
field (is it not final)
There are details to each strategy (see my questions above). If no staregy is matched, Mockito will fail silently. The fact that you are passing an object in constructor, and rely on setter or field injection afterwards makes this code unnecesarily complex.
I have a class ManageUser as below:
public class ManageUser {
private static UserBO gUserBO = new UserBO();
public String method1() {
gUserBO.callSomeFunction();
gUserBO.callSomeOtherFunction();
}
}
Now, I have a test class where I want to test method1() and since the methods callSomeFunction() and callSomeOtherFunction() end up making database calls I want to mock the calls to those methods. I am unable to do that by using mock since the object in ManageUser is static. How do I proceed? I am new to Junit and Mockito and can't seem to find relevant answers.
Try using Power Mockito:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ManageUser.class})
public class ClassInTest {
#Test
public void testStatic() {
ManageUser mUser = new ManageUser();
Field field = PowerMockito.field(ManageUser.class, "gUserBO");
field.set(ManageUser.class, mock(UserBO.class));
...
}
}
You are "unable to do that by using mock" because your class is badly designed. As a workaround, you could use PowerMock (as #S.K. suggested) to mock the static field but that will only suppress the real problem of your class.
Better take the chance and improve the code for better testability and evolvability:
Step 1: Create an interface for your class UserBO and let it implement it.
public interface UserService {
void callSomeFunction();
void callSomeOtherFunction();
}
public class UserBO implements UserService { ... }
Step 2: Change your class ManageUser to get any implementation of UserService through a constructor.
public class ManageUser {
private final UserService userService;
public ManageUser(UserService userService) {
this.userService = userService;
}
public String method1() {
userService.callSomeFunction();
userService.callSomeOtherFunction();
}
}
Step 3: Change the calling side of your class ManageUser to provide a UserService.
So instead of
ManageUser manager = new ManageUser();
use
ManageUser manager = new ManageUser(new UserBO());
Step 4: Now you can easily mock a UserService in your test and construct a ManageUser with the mock.
This design also enables DI frameworks (e.g. Spring) to inject (or autowire) the components.