I am using Mockito and have tried to mock the below test class.
Here the main class method createNewId() is getting the object by hitting dao class 'memberDao.findNext()'.
I am trying to mock 'memberDao.findNext()' and return the object as shown in below code but it is returning as NULL.
ALSO how to write Test for void method which is "memberDao.delete(newId.getId());"
Need to implement this after this line "when(memberDao.findNext()).thenReturn(id);"
Please let me know what am i doing wrong.
#RunWith(MockitoJUnitRunner.class)
public class MemberTest
{
#InjectMocks
private Member member;
#Mock
private MemberDao memberDao;
#Test
public void createId() throws Exception
{
MembersIdDto id = new MembersIdDto();
id.setId("967405286");
when(memberDao.findNext()).thenReturn(id);
verify(member).createNewId().contains("967405286");
}
public class Member {
#Resource
MemberDao memberDao;
public String createNewId()
{
MembersIdDto newId = memberDao.findNext();
Assert.notNull(newId, "newId is empty");
String id = newId.getId();
memberDao.delete(newId.getId());
return id;
}
}
memberDao.findNext() is the line i am trying to mock.
Error is :
java.lang.IllegalArgumentException: newId is empty
at org.springframework.util.Assert.notNull(Assert.java:134)
at Member.createNewId() (Member.java:20)
// Line 20 is "Assert.notNull(newId, "newId is empty");"
A working example of your requirement could be:
#RunWith(MockitoJUnitRunner.class)
public class MemberTest {
#InjectMocks
private Member member;
#Mock
private MemberDao memberDao;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void createId() throws Exception {
MembersIdDto dto = new MembersIdDto();
dto.setId("967405286");
when(memberDao.findNext()).thenReturn(dto);
assertThat(member.createNewId()).isEqualTo("967405286");
}
}
…with the classes-under-test…
public class Member {
#Resource
MemberDao memberDao;
public String createNewId() {
return memberDao.findNext().getId();
}
}
…and…
public class MemberDao {
public MembersIdDto findNext() {
return null; // or whatever
}
}
…and…
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#NoArgsConstructor
public class MembersIdDto {
private String id;
}
By the way, I use the AssertJ assertion framework and with member.createNewId() you have now a real call on production code.
You're creating two instances of MemberDao. First MockitoJUnitRunner creates an instance, assigns it to the field memberDao and injects that instance into the Member object. Afterwards in the method setUp you create a new instance of the DAO and assign it to the field memberDao. Therefore the field memberDao is no longer the same as the Member's DAO. While you define behaviour on the field, the Member object is still using the first DAO that has no behaviour defined. Therefore memberDao.findNext() in Member#createNewId returns null.
Fortunately the solution is very simple: Delete the setUp method in your test.
Related
There is an abstract class
public abstract class BaseProcessor {
public BooksTransaction getBooksTransaction() {
return booksTransaction;
}
}
There is another final class which is to be tested using Junit
public final class CreateOrganisationProcessor extends BaseProcessor {
public boolean process() throws Exception { //method to be tested
request = new CreateOrganisationRequest(IntegrationSystems.valueOf(getBooksTransaction().getSource()),
IntegrationSystems.valueOf(getBooksTransaction().getDestination()), getBooksTransaction());
request.setRequestTypes(getRequestTypes());
return true;
}
}
I tried spying the BaseProcessor class and mocking getBooksTransaction method to return BooksTransaction Object.
Code:
#Test
public void testProcess() throws Exception {
BaseProcessor spy = Mockito.spy(new CreateOrganisationProcessor());
BooksTransaction booksTransaction = new BooksTransaction();
booksTransaction.setReferenceID(DEFAULT_REFERENCE_ID);
Mockito.doReturn(booksTransaction).when(spy).getBooksTransaction();
}
Here, BooksTransaction is an JPA Entity class.
However, when I run the test case, the mock does not seem to be working, it does not return a BooksTransaction Object.
It neither throws an exception, nor any error.
I would like to know the right way to spy this method so that it returns me an object of BooksTransaction as per my mock.
I am new to Mockito, any help would be appreciable.
Thanks in advance.
It's funny that you got 5 up-votes for a question that does not even compile to begin with... I have simplified it just a bit, so that I could actually compile it, since I do not know your structure or can't even guess it correctly.
But the very first point you should be aware of is that Mockito can't by default mock final classes; you have a comment under your question that shows how to enable that.
#Getter
static abstract class BaseProcessor {
private BooksTransaction BooksTransaction;
}
#Getter
static class CreateOrganisationProcessor extends BaseProcessor {
CreateOrganisationRequest request;
public boolean process() { //method to be tested
request = new CreateOrganisationRequest(getBooksTransaction());
return true;
}
public CreateOrganisationRequest getRequest() {
return request;
}
}
#RequiredArgsConstructor
#Getter
static class BooksTransaction {
private final String testMe;
}
#Getter
#RequiredArgsConstructor
static class CreateOrganisationRequest {
private final BooksTransaction booksTransaction;
}
And here is a test that does work:
#Test
public void test() {
CreateOrganisationProcessor org = new CreateOrganisationProcessor();
CreateOrganisationProcessor spy = Mockito.spy(org);
System.out.println(spy);
BooksTransaction booksTransaction = new BooksTransaction("go!");
Mockito.doReturn(booksTransaction).when(spy).getBooksTransaction();
spy.process();
BooksTransaction mocked = spy.getRequest().getBooksTransaction();
Assert.assertEquals(mocked.getTestMe(), "go!");
}
And now think about it, you say in a comment : //method to be tested but you are not even calling it in your test, sounds fishy doesn't it? Than that method is defined in CreateOrganisationProcessor, but you are assigning your spy to:
BaseProcessor spy = Mockito.spy(new CreateOrganisationProcessor());
So now you can't even call process anymore on that spy reference, since it is not defined in BaseProcessor.
Assuming that I have this repository
#Repository public class GenericHistoryRepositoryImpl implements GenericHistoryRepository {
#Autowired private MongoTemplate mongoTemplate;
#Override public Historiable create(Historiable historiableObject, String collectionName) {
mongoTemplate.save(historiableObject, collectionName);
return historiableObject; }
#Override public <T extends Historiable> T get(String id, Class<T> collectionClass, String collectionName) {
Query query = new Query();
query.addCriteria(Criteria.where("id").is(id));
return mongoTemplate.findOne(query, collectionClass, collectionName);
} }
And I have this test in which I have to mock the repository, but I can't figure out how
#RunWith(MockitoJUnitRunner.class)
public class GenericHistoryServiceTest {
#Mock
private GenericHistoryRepository genericHistoryRepository;
#InjectMocks
private GenericHistoryService genericHistoryService = new GenericHistoryServiceImpl();
#Test
public <T extends Historiable> void getHistoryOk2() throws NotFoundException, ClassNotFoundException {
String id = "1"
;
String collectionName = HistoriableCollections.HISTORIABLE_SHIPMENT_REQUEST;
ShipmentRequest a = mock(ShipmentRequest.class);
Class<? extends Historiable> clazz = ShipmentRequest.class;
when(genericHistoryRepository.get(any(String.class), eq(clazz), collectionName)).thenReturn(createExample());
HistoriableDTO result = genericHistoryService.get(id, HistoriableCollections.HISTORIABLE_SHIPMENT_REQUEST);
// verify(genericHistoryRepository, times(1)).get(id, any(), HistoriableCollections.HISTORIABLE_SHIPMENT_REQUEST);
assertThat(result, is(notNullValue()));
assertThat(result.getId(), is(notNullValue()));
}
Keep in mind that Historiable is an abstract class
public abstract class Historiable {
public abstract String getParentId();
}
And this extends Historiable
#Document(collection = HistoriableCollections.HISTORIABLE_SHIPMENT_REQUEST)
public class ShipmentRequest extends Historiable {
private String id;
#Indexed
private String parentId;
...
}
My problem is with the "when" sentence defining the behaviour of the repository mock. It has generic methods that I don't know how to mock
Class<? extends Historiable> clazz = ShipmentRequest.class;
when(genericHistoryRepository.get(any(String.class), eq(clazz), collectionName)).thenReturn(createExample());
I'm getting
The method thenReturn(capture#1-of ? extends Historiable) in the type OngoingStubbing<capture#1-of ? extends Historiable> is not applicable for the arguments (ShipmentRequest)
private ShipmentRequest createExample() {
ShipmentRequest history = new ShipmentRequest();
history.setId("1");
return history;
}
Your when clause is the problem.
Inside the when you should define when to match and after that you state what should be returned.
Your when statement starts good by stating you want to match any String passed as first argument, but as a second argument you are passing a mock so that means that it will only trigger if that specific mock is passed as second argument (which I don't think is happening).
You can change the second argument to: any(Class.class)
For the third argument you can state that you want it to be equal to collectionName by using: org.mockito.ArgumentMatchers#eq(T)
In your test class you can have something like this
public class TestClass {
#Mock
GenericHistoryRepository genericHistoryRepository;
#InjectMock
MongoTemplate mongoTemplate;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
}
#InjectMock will inject the depedency of your mock.
I am newbie in Java world, but it is very hard understand why not can I stub method of a mocked object...
#RunWith(MockitoJUnitRunner.class)
public class ChildBLLIT extends BaseInteractorIT {
#InjectMocks
private ChildBLL ChildBLL = Mockito.mock(ChildBLL.class);
#Before
public void setUp() {
ChildBLL.engine = engineMock;
}
/**
* Test of getZipStatistics method, of class ChildBLL.
*/
#Test
public void testGetZipStatistics() {
final String testZipStatisticsText = "DummyZipStatistics";
//This method will throw the null pointer exception
when(ChildBLL.engine.getZIPStatistics()).thenReturn(testZipStatisticsText);
ChildBLL.getZipStatistics();
verify(ChildBLL.engine).getZIPStatistics();
}
}
When I try to stub the getZIPStatistics() method I get always a null pointer exception, of course I get, because in the getZIPStatistics() method there is an private object, which is not mocked... it seems to me the Mockito does not mocking the private fields... and unfortunately this is from another project:
public class BaseIT {
#Mock
protected static FromOtherProject engineMock;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
}
Here I mocked the engine variable, but then how can I mock/stub the getZIPStatistics() method? This is this method:
public class FromOtherProject {
//...
public final String getZIPStatistics() {
return ZIPStatistics.toString();
}
}
What can I do?
Let's assume a simple class...
public class Account {
public String getPassword() {
return "abc";
}
}
...and simple class that contains it...
public class AccountHolder {
private Account account;
public String getAccountPassword() {
return this.account.getPassword();
}
}
So now we have a simple base class for all Account based tests...
public class AccountBasedTest {
#Mock
protected Account account;
}
...and a class that actually tests the AccountHolder...
#RunWith(MockitoJUnitRunner.class)
public class AccountHolderTest extends AccountBasedTest {
#InjectMocks
private AccountHolder accountHolder;
#Test
public void getAccountPasswort_must_return_account_password() {
Mockito.when( this.account.getPassword() ).thenReturn ("xyz");
Assert.assertEquals("xyz", this.accountHolder.getAccountPassword());
}
}
And that's all. The #InjectMocks, etc. annotations will also look in the superclasses, so you get your mocked account and that account will be put into your AccountHolder. No need to call MockitoAnnotations.initMocks. It shouldn't hurt, but it's not needed because you are using the MockitoJUnitRunner already, which does exactly that.
I'm using EasyMock(version 2.4) and TestNG for writing UnitTest.
I have a following scenario and I cannot change the way class hierarchy is defined.
I'm testing ClassB which is extending ClassA.
ClassB look like this
public class ClassB extends ClassA {
public ClassB()
{
super("title");
}
#Override
public String getDisplayName()
{
return ClientMessages.getMessages("ClassB.title");
}
}
ClassA code
public abstract class ClassA {
private String title;
public ClassA(String title)
{
this.title = ClientMessages.getMessages(title);
}
public String getDisplayName()
{
return this.title;
}
}
ClientMessages class code
public class ClientMessages {
private static MessageResourse messageResourse;
public ClientMessages(MessageResourse messageResourse)
{
this.messageResourse = messageResourse;
}
public static String getMessages(String code)
{
return messageResourse.getMessage(code);
}
}
MessageResourse Class code
public class MessageResourse {
public String getMessage(String code)
{
return code;
}
}
Testing ClassB
import static org.easymock.classextension.EasyMock.createMock;
import org.easymock.classextension.EasyMock;
import org.testng.Assert;
import org.testng.annotations.Test;
public class ClassBTest
{
private MessageResourse mockMessageResourse = createMock(MessageResourse.class);
private ClassB classToTest;
private ClientMessages clientMessages;
#Test
public void testGetDisplayName()
{
EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
clientMessages = new ClientMessages(mockMessageResourse);
classToTest = new ClassB();
Assert.assertEquals("someTitle" , classToTest.getDisplayName());
EasyMock.replay(mockMessageResourse);
}
}
When I'm running this this test I'm getting following exception:
java.lang.IllegalStateException: missing behavior definition for the preceding method call getMessage("title")
While debugging what I found is, it's not considering the mock method call
mockMessageResourse.getMessage("ClassB.title") as it has been called from the construtor (ClassB object creation).
Can any one please help me how to test in this case.
Thanks.
You need to call EasyMock.replay(mock) before calling the method under test. After calling the method under test you can call EasyMock.verify(mock) to verify the mock is called.
Next you need to add another expect call with the "title" argument since you call it twice.
Code:
EasyMock.expect(mockMessageResourse.getMessage("title")).andReturn("title");
EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
EasyMock.replay(mockMessageResourse);
clientMessages = new ClientMessages(mockMessageResourse);
classToTest = new ClassB();
Assert.assertEquals("someTitle" , classToTest.getDisplayName());
EasyMock.verify(mockMessageResourse);
In my case, it was caused by the omission of a return value specification (andReturn(...)).
http://www.smcmaster.com/2011/04/easymock-issue-1-missing-behavior.html for more details.
This can have various causes (someMock is the name of your mocked Object in this answer).
On the one side it can be that you need to expect the call via
expect(someMock.someMethod(anyObject()).andReturn("some-object");
like in Reda's answer.
It can also be that you forgot to call replay(someMock) before you used the mock, like you can see in Julien Rentrop's answer.
A last thing that is possible that wasn't mentioned here is that you used the mock somewhere else before in a test and forgot to reset the mock via reset(someMock).
This can happen if you have multiple Unit Tests like this:
private Object a = EasyMock.createMock(Object.class);
#Test
public void testA() throws Exception {
expect(a.someThing()).andReturn("hello");
replay(a);
// some test code and assertions etc. here
verify(a);
}
#Test
public void testB() throws Exception {
expect(a.someThing()).andReturn("hello");
replay(a);
// some test code and assertions etc. here
verify(a);
}
This will fail on one test with the IllegalStateException, because the mock a was not reset before being used in the next test. To solve it you can do the following:
private Object a = EasyMock.createMock(Object.class);
#Test
public void testA() throws Exception {
expect(a.someThing()).andReturn("hello");
replay(a);
// some test code and assertions etc. here
verify(a);
}
#Test
public void testB() throws Exception {
expect(a.someThing()).andReturn("hello");
replay(a);
// some test code and assertions etc. here
verify(a);
}
#After
public void tearDown() throws Exception {
reset(a); // reset the mock after each test
}
You should put your call to replay after the expect calls, and before you use your mock. In this case you should change your test to something like this:
#Test
public void testGetDisplayName()
{
EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
EasyMock.replay(mockMessageResourse);
clientMessages = new ClientMessages(mockMessageResourse);
classToTest = new ClassB();
Assert.assertEquals("someTitle" , classToTest.getDisplayName());
}
For me, this exception was occurring because the method I was trying to stub was final (something I hadn't realized).
If you want to stub a final method you'll need to use Powermock.
I'm new to mock testing.
I want to test my Service method CorrectionService.correctPerson(Long personId).
The implementation is not yet written but this it what it will do:
CorrectionService will call a method of AddressDAO that will remove some of the Adress that a Person has. One Person has Many Addresses
I'm not sure what the basic structure must be of my CorrectionServiceTest.testCorrectPerson.
Also please do/not confirm that in this test i do not need to test if the adresses are actually deleted (should be done in a AddressDaoTest), Only that the DAO method was being called.
Thank you
Cleaner version:
#RunWith(MockitoJUnitRunner.class)
public class CorrectionServiceTest {
private static final Long VALID_ID = 123L;
#Mock
AddressDao addressDao;
#InjectMocks
private CorrectionService correctionService;
#Test
public void shouldCallDeleteAddress() {
//when
correctionService.correct(VALID_ID);
//then
verify(addressDao).deleteAddress(VALID_ID);
}
}
A simplified version of the CorrectionService class (visibility modifiers removed for simplicity).
class CorrectionService {
AddressDao addressDao;
CorrectionService(AddressDao addressDao) {
this.addressDao;
}
void correctPerson(Long personId) {
//Do some stuff with the addressDao here...
}
}
In your test:
import static org.mockito.Mockito.*;
public class CorrectionServiceTest {
#Before
public void setUp() {
addressDao = mock(AddressDao.class);
correctionService = new CorrectionService(addressDao);
}
#Test
public void shouldCallDeleteAddress() {
correctionService.correct(VALID_ID);
verify(addressDao).deleteAddress(VALID_ID);
}
}