How to spy parameter 'param' in nested method during getData() mock testing ?
Is it possible with Easymock 3 ?
Source code
public class ServiceLogic {
public void getData(){
// some business logic
serviceDAO.executeStatement(param);
}
}
Easymock test :
ServiceLogic _serviceLogicMock = EasyMock.createNiceMock(ServiceLogic.class);
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);
_serviceLogicMock.setServiceDAO(_serviceDAOMock);
//some other method calls -> .execute(...).andReturn(...);
EasyMock.replay(_serviceLogicMock);
//run
_serviceLogicMock.getData();
How to check with EasyMock whether executeStatement() method is called with correct parameter ?!
Your test does seem wrong:
Your unit test is about testing ServiceLogic why do you mock it then ?
Also you don't have any expectations on any interaction with your ServiceDAO mock.
As the question is tagged Mockito, I propose the following solution (minus the imports) that you can adapt to your code :
#RunWith(MockitoJUnitRunner.class)
public class ServiceLogicTest {
#Mock ServiceDAO serviceDAO;
#InjectMocks ServiceLogic serviceLogic;
#Test
public void ensure_executeStatement_is_called_with_right_param() throws Exception {
// given
String input = "Some input";
// when
serviceLogic.getDataFrom(input);
// then
verify(serviceDAO).executeStatement("expected param");
}
}
When writing tests, I like to use the BDD (Behavior Driven Development) style to guide me to what I want to test. I encourage you to practice it, you can have look at the wiki page.
So for your question, you should take a look at the verify line, it put the mock in a verification mode, so can actually verify that the method executeStatement is actually called with the argument value "expected param".
If you have more complex parameters, you can use some matchers using the Hamcrest library:
verify(serviceDAO).executeStatement(argThat(hasProperty("propertyName")));
Or you can use a Mockito's ArgumentCaptor in combination with the FEST-Assert library (usually my preferred approach):
ArgumentCaptor<ComplexArgument> argCaptor = ArgumentCaptor.forClass(ComplexArgument.class);
verify(serviceDAO).executeStatement(argCaptor.capture());
assertThat(argCaptor.getValue()).isNotNull().satisfies(myComplexArgumentCondition());
The main idea is to have understandable code, in production code and in test code.
For further reading have a look at the Mockito Javadoc.
Like #Brice, I prefer Mockito to EasyMock, but here's the EasyMock version that is closer to your original example since your example was EasyMock.
public class ServiceLogicTest {
#Test
public void ensure_executeStatement_is_called_with_right_param() throws Exception {
ServiceLogic _serviceLogicUT = new ServiceLogic();
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);
_serviceLogicUT.setServiceDAO(_serviceDAOMock);
String input = "Some input";
//some other method calls -> .execute(...).andReturn(...);
_serviceDaoMock.executeStatement("expected para"); // assuming a void method
EasyMock.replay(_serviceDaoMock);
// run
_serviceLogicUT.getDataFrom(input);
// verifies that the expected calls were made
EasyMock.verify(_serviceDaoMock);
}
}
EasyMock also has argument capture functionality. That would look like this:
public class ServiceLogicTest {
#Test
public void ensure_executeStatement_is_called_with_right_param() throws Exception {
ServiceLogic _serviceLogicUT = new ServiceLogic();
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);
_serviceLogicUT.setServiceDAO(_serviceDAOMock);
String input = "Some input";
//some other method calls -> .execute(...).andReturn(...);
Capture<ComplexParam> capturedParam = new Capture<ComplexParam>();
_serviceDaoMock.executeStatement(EasyMock.capture(capturedParam)); // assuming a void method
EasyMock.replay(_serviceDaoMock);
// run
_serviceLogicUT.getDataFrom(input);
ComplexParam actualParam = capturedParam.getValue();
// make various assertions on actual param
}
}
I think you can see from the two examples why many people prefer Mockito, but if there's some reason you prefer or are mandated to use EasyMock, you can do just about anything you can do with Mockito, just with more lines of code.
This should be possible with jmockit, unless you DAO has final methods. However, this is better and easier done with jMockit:
#Test
public void testMethod(#Mocked final ServiceDAO serviceDAO) {
new Expectations() {{
serviceDAO.executeStatement(expectedOParams);returns(expectedReturnValue)
}};
(new ServiceLogic(serviceDAO)).getData();
}
That's almost complete test save assertions. And it works with final, static, abstract and whatever methods.
Related
I was playing with org.springframework.data.jpa.domain.Specifications, it's just a basic search :
public Optional<List<Article>> rechercheArticle(String code, String libelle) {
List<Article> result = null;
if(StringUtils.isNotEmpty(code) && StringUtils.isNotEmpty(libelle)){
result = articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)).and(ArticleSpecifications.egaliteLibelle(libelle)));
}else{
if(StringUtils.isNotEmpty(code)){
result= articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)));
}else{
result = articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteLibelle(libelle)));
}
}
if(result.isEmpty()){
return Optional.empty();
}else{
return Optional.of(result);
}
}
And that's actually working fine but I'd like to write unit tests for this method and I can't figure out how to check specifications passed to my articleRepository.findAll()
At the moment my unit test looks like :
#Test
public void rechercheArticle_okTousCriteres() throws FacturationServiceException {
String code = "code";
String libelle = "libelle";
List<Article> articles = new ArrayList<>();
Article a1 = new Article();
articles.add(a1);
Mockito.when(articleRepository.findAll(Mockito.any(Specifications.class))).thenReturn(articles);
Optional<List<Article>> result = articleManager.rechercheArticle(code, libelle);
Assert.assertTrue(result.isPresent());
//ArgumentCaptor<Specifications> argument = ArgumentCaptor.forClass(Specifications.class);
Mockito.verify(articleRepository).findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)).and(ArticleSpecifications.egaliteLibelle(libelle)));
//argument.getValue().toPredicate(root, query, builder);
}
Any idea?
I was having almost the same problems as you had, and I changed my class that contains Specifications to be an object instead of just one class with static methods. This way I can easily mock it, use dependency injection to pass it, and test which methods were called (without using PowerMockito to mock static methods).
If you wanna do like I did, I recommend you to test the correctness of specifications with integration tests, and for the rest, just if the right method was called.
For example:
public class CdrSpecs {
public Specification<Cdr> calledBetween(LocalDateTime start, LocalDateTime end) {
return (root, query, cb) -> cb.between(root.get(Cdr_.callDate), start, end);
}
}
Then you have an integration test for this method, which will test whether the method is right or not:
#RunWith(SpringRunner.class)
#DataJpaTest
#Sql("/cdr-test-data.sql")
public class CdrIntegrationTest {
#Autowired
private CdrRepository cdrRepository;
private CdrSpecs specs = new CdrSpecs();
#Test
public void findByPeriod() throws Exception {
LocalDateTime today = LocalDateTime.now();
LocalDateTime firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
LocalDateTime lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
List<Cdr> cdrList = cdrRepository.findAll(specs.calledBetween(firstDayOfMonth, lastDayOfMonth));
assertThat(cdrList).isNotEmpty().hasSize(2);
}
And now when you wanna unit test other components, you can test like this, for example:
#RunWith(JUnit4.class)
public class CdrSearchServiceTest {
#Mock
private CdrSpecs specs;
#Mock
private CdrRepository repo;
private CdrSearchService searchService;
#Before
public void setUp() throws Exception {
initMocks(this);
searchService = new CdrSearchService(repo, specs);
}
#Test
public void testSearch() throws Exception {
// some code here that interact with searchService
verify(specs).calledBetween(any(LocalDateTime.class), any(LocalDateTime.class));
// and you can verify any other method of specs that should have been called
}
And of course, inside the Service you can still use the where and and static methods of Specifications class.
I hope this can help you.
If you are writing Unit Tests then you should probably mock the call to findAll() method of articleRepository Class using a mocking framework like Mockito or PowerMock.
There is a method verify() using which you can check if the mock is invoked for the particular parameters.
For Example, if you are mocking the findAll() method of articleRepository Class and want to know if this method is called with particular arguments then you can do something like:
Mokito.verify(mymock, Mockito.times(1)).findAll(/* Provide Arguments */);
This will fail the test if mock has not been called for the arguments that you provided.
Your problem is that you are doing too many things within that one method. You should have three different methods that work on articleRepository.
Then you can use mocking as the others suggest:
setup your mocks so that you know which call on articleRepository should be made
verify that exactly the expected calls are happening
Please note: these three methods should be internal; the main point there is: you can't test this method with ONE call from the outside; as it is doing more than one thing, depending on the input that you provide. Thus you need to create at least one test method for each of the potential paths in your code. And that becomes easier (from a conceptual point of view) when you separate your code into different methods.
I have an internal StreamGobbler class that has 7 methods in it.
I'm looking for a quick way to mock all the methods by default, but override one method named getOutput() (e.g. Partial Mocking).
(full code not shown for clarity)
public class StreamGobbler extends Thread
{
public String getOutput()
public void run()
}
What I would like is to use something like the #Mocked annotation in combination with MockUp to partially mock the getOutput method, but retain all the "default" mocking code on all the other methods. In the docs on partial mocking, it makes the point that if you use MockUp, all non #Mock methods retain their normal functionality. Sometimes that is great, but that isn't what I want in this case.
This is similar to the question JMockit: #Mocke and MockUp combination in the same test, but I can't get away with just looking at method counts.
If I have a test setup like this:
#Test
public void execute(#Mocked StreamGobbler sg)
{
new MockUp<StreamGobbler>()
{
String type = null;
#Mock
void $init(String type)
{
this.type = type;
}
#Mock
String getOutput()
{
if ("OUTPUT".equals(type))
{
return "test output";
}
else
{
return "";
}
}
}
}
I get this error java.lang.IllegalArgumentException: Class already mocked
If I try to add the #Override annotation in the MockUp, it doesn't help (and Eclipse complains about it)
What is the best way to handle this? Use a static class outside this test method?
Using JMockit 1.17, and TestNG
In summary, how do I get every method in StreamGobbler mocked (as with #Mocked), but partially override one method (without manually doing it myself inside the MockUp?)
Full example code which meets the given constraints:
public static class StreamGobbler extends Thread {
public StreamGobbler(String type) {}
public String getOutput() { return null; }
#Override public void run() {}
}
public static class TestedClass {
public String doSomething() throws InterruptedException {
StreamGobbler sg1 = new StreamGobbler("OUTPUT");
sg1.start();
StreamGobbler sg2 = new StreamGobbler("ERROR");
sg2.start();
sg1.join(5000);
sg2.join(5000);
String output1 = sg1.getOutput();
String output2 = sg2.getOutput();
return output1 + '|' + output2;
}
}
#Test
public void useStreamGobbler(#Mocked StreamGobbler sg) throws Exception {
new Expectations() {{
new StreamGobbler("OUTPUT").getOutput(); result = "test output";
new StreamGobbler("ERROR").getOutput(); result = "";
}};
String output = new TestedClass().doSomething();
assertEquals("test output|", output);
}
Firstly, since you are creating an anonymous subclass of the MockUp class, using the #Override annotation would certainly be inappropriate. Those methods that you are providing do not belong to the MockUp class, but the generic you are providing.
Later on during runtime, (through some impressive process (based on what I read here, I'm assuming AOP)) the instance you create in this class will then use your provided method signatures instead of its own.
After reading the API on the Mock class more thoroughly as well as getting some information from JMockit's Getting Started page, I think you're issue lies in a different area entirely. If you have other test methods, they will be interfering with this method.
The error you are getting is saying: "There is already an instance of MockUp declared for the type StreamGobbler, and by calling the Mocked annotation in this test method's parameters and attempting to declare another instance of MockUp with the same generic, you are violating a JMockit stipulation."
I would check to see if you are creating an actual MockUp of StreamGobbler outside of the test method and if so (1) if you want to use it, don't redeclare another instance of MockUp in the method but continue to use the Mocked annotation or (2) if you do not want to use it and you want to re-declare a new instance of MockUp wrapping StreamGobbler, do not use the Mocked annotation in the test method's parameters but keep the MockUp instantiation.
public class First {
public First(){
}
public String doSecond(){
Second second = new Second();
return second.doJob();
}
}
class Second {
public String doJob(){
return "Do Something";
}
}
Here I want to test the method "doSecond()" of class "First". For the same, I want to mock the method "doJob" of class "Second".
I know that I can create a mocked instance of class "Second" using the code below.
Second sec = mock(Second.class);
when(sec.doJob()).thenReturn("Stubbed Second");
But I cannot relate this mocked instance with class "First" as of the current code.
Without refactoring the source code, is there any way by which i can achieve the requirement.
Please help.
Take a look at powermock's ability to intercept calls to new and return mocks instead
https://code.google.com/p/powermock/wiki/MockConstructor
This doesn't require changing any sourcecode.
here's the test code where we actually return a mock when First.doSecond() calls new Second()
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class TestFirst {
#Test
public void mockSecond() throws Exception{
Second mock = PowerMockito.mock(Second.class);
PowerMockito.whenNew(Second.class).withNoArguments().thenReturn(mock);
PowerMockito.when(mock.doSecond()).thenReturn("from mock");
First first = new First();
assertEquals("from mock", first.doSecond());
}
}
It's tricky to mock an instance that you create inside of a method, but it's possible.
Using PowerMock, you can accomplish this with the PowerMock.expectNew() method:
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class StackOverflowTest {
#Test
public void testFirst() throws Exception {
Second secondMock = EasyMock.createMock(Second.class);
PowerMock.expectNew(Second.class).andReturn(secondMock);
expect(secondMock.doSecond()).andReturn("Mocked!!!");
PowerMock.replay(secondMock, Second.class);
String actual = new First().doSecond();
PowerMock.verify(secondMock, Second.class);
assertThat(actual, equalTo("Mocked!!!"));
}
}
Effectively, PowerMock is proxying the creation of the new object and substituting whatever value we want when we invoke doSecond().
So, it's possible. However, this is a terrible practice to get into.
One typically wants to mock objects if they involve an outside concern, such as another layer (i.e. database, validation), or if the desired output is coming from other objects that are injected but are safe enough to consider tested.
If your method is capable of getting or retrieving data from a non-injectable source, you should not want to mock that out.
Considering that your method is simple and straightforward, you should really not need to do any mocks here at all. But if you felt that you were forced to, you could do one of a few things:
Create a factory for the creation of Second, and mock the results of the returning factory object with Mockito.
Pass in an instance of Second to that method, and use Mockito as the mock instance.
Declare it as a field (i.e. injected dependency), and use Mockito.
For completeness, here is how the test can be written with the JMockit mocking API, without any refactoring of the original code under test:
public class ExampleTest
{
#Test
public void firstShouldCallSecond(#Mocked final Second secondMock) {
new NonStrictExpectations() {{
secondMock.doJob(); result = "Mocked!!!";
}};
String actual = new First().doSecond();
assertEquals("Mocked!!!", actual);
}
}
I am using the following.
Powermock-mockito 1.5.12
Mockito 1.95
junit 4.11
Here is my utils class
public void InternalUtils {
public static void sendEmail(String from, String[] to, String msg, String body) {
}
}
here is gist of the class under test:
public class InternalService {
public void processOrder(Order order) {
if (order.isSuccessful()) {
InternalUtils.sendEmail(...);
}
}
}
And here is the test:
#PrepareForTest({InternalUtils.class})
#RunWith(PowerMockRunner.class)
public class InternalService {
public void verifyEmailSend() {
mockStatic(Internalutils.class);
doNothing().when(InternalUtils, "sendEmail", anyString(), any(String.class), anyString(), anyString());
Order order = mock(Order.class);
when(order.isSuccessful()).thenReturn(true);
InternalService is = new InternalService();
verifyStatic(times(1));
is.processOrder(order);
}
}
The above test fails. The verification mode given is none, but according to the code, if order is successful than email must be send.
If you are mocking the behavior (with something like doNothing()) there should really be no need to call to verify*(). That said, here's my stab at re-writing your test method:
#PrepareForTest({InternalUtils.class})
#RunWith(PowerMockRunner.class)
public class InternalServiceTest { //Note the renaming of the test class.
public void testProcessOrder() {
//Variables
InternalService is = new InternalService();
Order order = mock(Order.class);
//Mock Behavior
when(order.isSuccessful()).thenReturn(true);
mockStatic(Internalutils.class);
doNothing().when(InternalUtils.class); //This is the preferred way
//to mock static void methods.
InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
//Execute
is.processOrder(order);
//Verify
verifyStatic(InternalUtils.class); //Similar to how you mock static methods
//this is how you verify them.
InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
}
}
I grouped into four sections to better highlight what is going on:
1. Variables
I choose to declare any instance variables / method arguments / mock collaborators here. If it is something used in multiple tests, consider making it an instance variable of the test class.
2. Mock Behavior
This is where you define the behavior of all of your mocks. You're setting up return values and expectations here, prior to executing the code under test. Generally speaking, if you set the mock behavior here you wouldn't need to verify the behavior later.
3. Execute
Nothing fancy here; this just kicks off the code being tested. I like to give it its own section to call attention to it.
4. Verify
This is when you call any method starting with verify or assert. After the test is over, you check that the things you wanted to have happen actually did happen. That is the biggest mistake I see with your test method; you attempted to verify the method call before it was ever given a chance to run. Second to that is you never specified which static method you wanted to verify.
Additional Notes
This is mostly personal preference on my part. There is a certain order you need to do things in but within each grouping there is a little wiggle room. This helps me quickly separate out what is happening where.
I also highly recommend going through the examples at the following sites as they are very robust and can help with the majority of the cases you'll need:
https://github.com/powermock/powermock/wiki/Mockito (PowerMock Overview / Examples)
http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html (Mockito Overview / Examples)
Thou the above answer is widely accepted and well documented, I found some of the reason to post my answer here :-
doNothing().when(InternalUtils.class); //This is the preferred way
//to mock static void methods.
InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
Here, I dont understand why we are calling InternalUtils.sendEmail ourself.
I will explain in my code why we don't need to do that.
mockStatic(Internalutils.class);
So, we have mocked the class which is fine.
Now, lets have a look how we need to verify the sendEmail(/..../) method.
#PrepareForTest({InternalService.InternalUtils.class})
#RunWith(PowerMockRunner.class)
public class InternalServiceTest {
#Mock
private InternalService.Order order;
private InternalService internalService;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
internalService = new InternalService();
}
#Test
public void processOrder() throws Exception {
Mockito.when(order.isSuccessful()).thenReturn(true);
PowerMockito.mockStatic(InternalService.InternalUtils.class);
internalService.processOrder(order);
PowerMockito.verifyStatic(times(1));
InternalService.InternalUtils.sendEmail(anyString(), any(String[].class), anyString(), anyString());
}
}
These two lines is where the magic is,
First line tells the PowerMockito framework that it needs to verify the class it statically mocked. But which method it need to verify ??
Second line tells which method it needs to verify.
PowerMockito.verifyStatic(times(1));
InternalService.InternalUtils.sendEmail(anyString(), any(String[].class), anyString(), anyString());
This is code of my class, sendEmail api twice.
public class InternalService {
public void processOrder(Order order) {
if (order.isSuccessful()) {
InternalUtils.sendEmail("", new String[1], "", "");
InternalUtils.sendEmail("", new String[1], "", "");
}
}
public static class InternalUtils{
public static void sendEmail(String from, String[] to, String msg, String body){
}
}
public class Order{
public boolean isSuccessful(){
return true;
}
}
}
As it is calling twice you just need to change the verify(times(2))... that's all.
Let's say you have some 3rd-party library class that you want to extend, simply to add convenience methods to it (so you can call an inherited method with default parameters for example).
Using jUnit/jMock, is it possible to write an assertion / mock expection that tests that the correct inherited method is called?
For example, something like this:
class SomeClass extends SomeLibraryClass {
public String method(String code) {
return method(code, null, Locale.default());
}
}
How can I assert that method is being called?
You can make a further subclass inside your unit test that actually tells you:
public class MyTest {
boolean methodCalled = false;
#Test
public void testMySubclass(){
TestSomeClass testSomeClass = new TestSomeClass();
// Invoke method on testSomeclass ...
assertTrue( methodCalled);
}
class TestSomeClass extends SomeClass{
public String method(String code){
methodCalled = true;
}
}
}
Unit testing is more useful to verify the functionality of given methods, not to assert coverage. Unit tests that care more about what method got called know way more about the classes they are testing than they probably should, not to mention will be confusing to the reader.
Coverage tools like Cobertura or EMMA will tell you whether you properly covered your code.
It may indeed be better to only write integration tests in this case, but if you really want a unit test, you can have it just as easily as in any other case:
public class SomeClassTest
{
#Test
public void testMethod()
{
final String code = "test";
new Expectations()
{
SomeLibraryClass mock;
{
mock.method(code, null, (Locale) any);
}
};
new SomeClass().method(code);
}
}
This test uses the JMockit mocking API.
it's hard to tell without a more concrete example, but I'd guess that this ought to be an integration test--test the whole package together--rather than a unit test. Sometimes one can be too fine-grained with unit testing.