I am new to Mockito.
I am trying to write jnuit for a service by mocking the db interactions:
I have following classes (just representative of actual classes)
public class TestService{
public Response getTestList(String type){
list = getListbyType(type);
return response.entity(list);
}
private List getListbyType(String type){
...
..
TestDAO testdao = new Testdao(sqlconn);
list = testdao.getListfromDB(type)
return list;
}
}
And my test class is something like
public class TestServiceTest{
#InjectMocks
private TestService testService = new TestService();
#Test
public void getTestListTest(){
List testlist = new List();
tetslist.add("test1");
TestDAO testdaomock = mock(TestDAO);
when(testdaomock.getListfromDB("test")).thenreturn(list);
list = testService.getTestList(test);
}
}
But when I run this test, it still invokes the actual DB call and retrieves the values from db and not the mocked values, should I mock sql connection and non default constructor? I am clueless.
-- UPDATE
As people have suggested, I moved DAO instantiation to my service constructor and also used Spy, But still my actual DB call is invoked instead of the mock call.
Your problem is with the following statement:
TestDAO testdao = new Testdao(sqlconn);
The instance of TestDAO you got from mock() is not the instance used in testdao.getListfromDB(type) that follows new
In order to successfully mock, you need to apply the inversion of dependencies throughout. That means new must only show up in classes you don't intend to test, such as simplistic factories or Spring config files.
[Update]
If proper IOC is not an option, you can introduce a method that allocates DAO and then spy() it. The method would have to be package-private. This is described here.
Another option would be to add a package-private constructor taking testdao as argument and expressing your default constructor in the terms of that constructor.
In case you can't change the TestService class (legacy code) there is a possiblity to mock the new instance with PowerMockito (https://github.com/jayway/powermock). This uses a own junit runner (PowerMockRunner) that allows the byte-code manipulation.
Here an example for your code:
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
public class TestServiceTest {
#Mock
TestDAO testDaoMock;
#Test
public void test() throws Exception {
List<String> testlist = new ArrayList<>();
testlist.add("test1");
when(testDaoMock.getListfromDB(anyString())).thenReturn(testlist);
PowerMockito.whenNew(TestDAO.class).withAnyArguments().thenReturn(testDaoMock);
TestService testService = new TestService();
Response actualResponse = testService.getTestList("testType");
assertEquals(expectedResponse, actualResponse);
}
}
You will need to add powermock-api-mockito and powermock-module-junit4 to your dependcies.
Related
In one of my controller
#Autowired
private Map<String, ABC> abcMap;
now I want mock it in one of the unit test but I always get null pointer exception.
This map contains implementations of ABC abstract class.
Can anyone suggest a possible solution?
I'm not sure what Unit test Framework you are using but there are ways of making it inject the mock details. You'll have to give us more information before before we can answer.
Personally I don't much like Autowired private fields, so at the risk of answering a different question can I suggest you consider using an Autowired constructor instead. From Springs POV it won't make a difference, your object will be create and all the appropriate data wired in. (OK, there is a slight change in the order things are done, but generally you won't notice). You will have to write a constructor to copy the constructor parameters to private fields, but:
Those fields could be made final, which could make your class safer
Your Unit tests wont need any 'magic' to initialise the Autowired fields - just pass parameters
If you refactor you class to remove add/remove/modify an Autowired field then you have to remember to change your test code. With an Autowired constructor you test code has to be changed or it won't compile, and your IDE might even help you do it.
Update
The Autowired constructor alternative looks something like:
#Controller
class MyClass {
private final Class1 bean1;
private final Object value2;
#Autowired
MyClass(Class1 bean1, Class2 bean2) {
this.bean1 = bean1;
this.value2 = bean2.getValue();
}
}
Keys points are:
The class has just one constructor and it requires parameters.
The fields are not annotated #Autowired, because Spring is not assigning values to them; the constructor does that.
The constructor IS annotated as #Autowired to tell Spring to pass the beans as parameters
The first parameter is stored in a final variable - you code can't accidentally over write it, so your code is safer
In my example the second parameter is only used in the constructor, so we don't have to store it as a field in your controller. I often to this if the Bean is an object that passes configuration around.
A No-argument constructor is not required
At test time your code will have to pass parameters to the class.
Your test code will look something like:
class MyClassTest {
private Class1 bean1;
private Class2 bean2;
private MyClass objectUnderTest;
#Before
public void setUp() throws Exception {
bean1 = mock(Class1.class);
bean2 = mock(Class2.class);
// Train mocks here
objectUnderTest = new MyClass(bean1, bean2)
}
#Test
public void myTest() {
// Do something with objectUnderTest
}
}
Key points are:
There are no #MockBean annotations
The Unit test is only using the API that your Controller bean defines; No black magic is required
It's not possible to create a MyClass with out providing the required data. This is enforced by the compiler
I think you can try it.
The sample of code:
public interface Animal {
}
#Service
public class Cat implements Animal{
}
#Service
public class Dog implements Animal{
}
#Service
public class Clinic {
#Autowired
private final Map<String, Animal> animalMap = new HashMap<>(2);
}
Sample of test
#Configuration
public class TestEnvConfig {
#Bean
public Clinic create(){
return new Clinic();
}
#MockBean // you can do it without mock or use #ComponentScan
Dog dog;
#MockBean
Cat cat;
}
#SpringBootTest(classes = TestEnvConfig.class)
#RunWith(SpringRunner.class)
public class ClinicTest {
#Autowired
private Clinic clinic;
}
I have a dependency in the Spring Boot which is called from my class. This dependency makes a call with a newly instantiated builder pattern class as an argument. I need to know if it is possible to verify if this single builder class was constructed with certain values when the dependency call is made, e.g.:
public class MyClass {
#Autowired
private MyDep myDep;
public void callMyDepService() {
myDep.serviceCall(new MyBuilder().paramOne("One").paramTwo("Two").build());
}
}
As you can see, a new MyBuilder is instantiated every time, so I can't just use Mockito's eq() to match the arguments' value.
I would like to make sure callMyDepService calls myDep.serviceCall with certain parameter values.
Using a captor seems to be the easiest way to do that.
Something like this, where SomeClass is the class your MyBuilder builds.
#ExtendWith(MockitoExtension.class)
public class CaptureTest {
#InjectMocks
MyClass classUnderTest;
#Mock
MyDep myDep;
#Test
public void test() {
classUnderTest.callMyDepService();
Captor<SomeClass> captor = ArgumentCaptor.forClass(SomeClass.class);
Mockito.verify(myDep).serviceCall(captor.capture());
SomeClass parameter = captor.getValue();
// do assertions
}
}
I am looking to mock out a Domain Dependency while I test a Service Class, using JMockit. The problem is, that the Domain object is instantiated in one of the Service's methods, and the Domain constructor used, has parameters.
Domain Class:
package com.example;
public class DomainClass {
String str;
public DomainClass(String s) {
str=s;
}
public String domainMethod() {
return str;
}
}
Service Class
package com.example;
public class ServiceClass {
public String serviceMethod() {
return new DomainClass("original").domainMethod();
}
}
How do I mock out the DomainClass that the ServiceClass is using?
Note: I am not looking to change the Domain or Service classes. (I realize that this code is is trivial and could be written better, but it is just a simple example of more complex code.)
Test Class (Final Answer)
package com.example;
import org.testng.*;
import org.testng.annotations.*;
import mockit.*;
public class TestClass {
#Mocked DomainClass domainClass;
#Test
public void testMethod() {
new Expectations() {{
new DomainClass("original").domainMethod(); result = "dummy";
}};
String ss = new ServiceClass().serviceMethod();
System.out.println(ss);
Assert.assertEquals(ss, "dummy");
}
}
The JMockit documentation should answer that.
Anyway, to mock a class, simply use #Mocked DomainClass (as mock field or test method parameter).
BTW, having new DomainClass("original").domainMethod() is not "bad design" (on the contrary, turning it into a singleton - injected or not - would be). However, mocking such classes may very well be a bad idea; always prefer not mocking.
Example:
public class myClass {
private WebService webService;
public void process(String delimitedString) {
String[] values = StringUtils.split(delimitedString, "$%");
insideMethod.setFirstName(values[0]);
insideMethod.setMiddleName(values[1]);
insideMethod.setLastName(values[2]);
insideMethod.setBirthDate(values[3]);
webService.getResponseWS(insideMethod.getFirstName,
insideMethod.getMiddleName,
insideMethod.getLastName,
insideMethod.getBirthDate);
}
}
I want to test that the right values are being set in insideMethod to make sure that the correct parameters are being passed to webService.getResponseWS()
This is in Java and I should use unit tests and Mokito.
Note: I am not testing the webService method. I need to test that the values passed to insideMethod are correct. Example "John" for name instead of "JohnSm" or "John$%".
So far I have created a test class, instantiated the class being tested and mocked the webService class.
public class TestClass {
MyClass myClass = new MyClass();
private WebService webService = mock(WebService.class);
public void processTest() {
when(webService.getResponseWS()).thenCallRealMethod();
insideMethod.process("John$%J$%Smith$%02-02-1990");
You want to use Mockito.verify().
The JavaDoc aor the Mockito Verify Cookbook lists a lot of examples.
import static org.mockito.Mockito.verify;
#RunWith(MockitoJUnitRunner.class)
public class TestClass {
#Mock
private WebService webService;
private MyClass myClass = new MyClass();
#Test
public void processTest() {
// inject webService mocked instance into myClass instance, either with a setter
myClass.setWebService(webService);
// or using Mockito's reflection utils if no setter is available
//Whitebox.setInternalState(myClass, "webService", webService);
// call the method to be tested
String input = "input"; // whatever your input should be for the test
myClass.process(input);
// verify webService behavior
verify(webService).getResponseWs(
"expectedInput1", "expectedInput2", "expectedInput3", "expectedInput4");
}
}
Provided you've set up Mockito and injected your mocks correctly, the following should work (although I don't have a compiler or JVM at hand to check).
verify(webService).getResponseWS("John", "J", "Smith", "02-02-1990");
I'm using Java 6, JUnit 4.8.1, and writing a console application. My application has a member field that isn't exposed …
public class MyApp {
...
private OpportunitiesService m_oppsSvc;
private void initServices() {
…
m_oppsSvc = new OpportunitiesServiceImpl(…);
}
...
}
I want to mock a behavior such that whenever one method from my service is called, (e.g. m_oppsSvc.getResults()), the same result is always returned. How do I do that? There's no setter method for the field. I'm currently working with Mockito 1.8.4. Is it possible to do this with Mockito or some other mock framework?
This is what you want:
#RunWith(MockitoJUnitRunner.class)
public class MyAppTest {
#Mock private OpportunitiesService mocked_m_oppsSvc;
#InjectMocks MyApp myApp;
#Test public void when_MyApp_uses_OpportunititesService_then_verify_something() {
// given
given( mocked_m_oppsSvc.whatever()).willReturn(...);
// when
myApp.isUsingTheOpportunitiesService(...);
// then
verify...
assertThat...
}
}
Using: Mockito 1.9.0, BDD style, FEST-Assert AssertJ.
Hope that helps :)
Given that you're already using mockito, why not just use reflection:
#RunWith(MockitoJUnitRunner.class)
public class MyApp {
#Mock
private OpportunitiesService m_oppsSvc;
private MyApp myApp;
#Before
public void before() throws Exception {
myApp = new MyApp();
Field f = MyApp.class.getDeclaredField("m_oppsSvc");
f.setAccessible(true);
f.set(myApp, m_oppsSvc);
}
}
It's a bit ugly, but it will do the trick. Note that this may not be the most efficient way to do it with Mockito, but it will work.
There's also Powermock which should allow you to do this as well using the Whitebox class. I won't get into the whole details of Powermock but here's the call to inject the private field value, which should be a mock object:
Whitebox.setInternalState(myApp, "m_oppsSvc", m_oppsSvc);
You should consider attempts to mock a private field a smell. That is, a sign that either what you're trying to do is either incorrect or that your code is currently structured incorrectly. You should only need to mock public methods or injected dependencies
In the code you've given you should consider injecting OpportunitiesService as follows:
public class MyApp {
...
private OpportunitiesService m_oppsSvc;
public MyApp(OpportunitiesService oppsSvc) {
this.m_oppsSvc = oppsSvc;
}
...
}
In your test you can then inject a mock as follows:
OpportunitiesService mockOpportunitiesService =
Mockito.mock(OpportunitiesService.class);
Mockit.when(mockOpportunitiesService.someMethod()).thenReturn(someValue);
MyApp app = new MyApp(mockOpportunitiesService);
You can easily do it with JMockit:
public class MyAppTest
{
#Tested MyApp myApp;
#Test
public testSomething(final #Capturing OpportunitiesService mockService)
{
new NonStrictExpectations() {{
mockService.getResults(); result = asList("a", "b", "C");
// record other expectations, if needed
}};
myApp.whateverMethodIWantToTest();
new Verifications() {{
mockService.doSomething(anyInt);
// verify other expectations, if needed
}};
}
}
Even though the implementation class OpportunitiesServiceImpl isn't mentioned in test code, its instances (any number of them) will still get properly mocked.
Generally you should use dependency injection and pass the mock object (of type OppportunitiesServiceImpl) in via the constructor, a separate setter or directly to the method (getResults). You might need to extract an interface for OpportunitiesServiceImpl first.
Usually, this is solved through the use of dependency injection. In regular (production) mode, your dependency injection container (e.g. Spring or Guice) will inject an instance of OpportunitiesService into MyApp through your constructor or through a setter.
Then, when you're testing you can "inject" a mock instance manually using the same setter or constructor argument.
Instead of doing
m_oppsSvc = new OpportunitiesServiceImpl(…);
Try Passing OpportunitesService in through MyApp's constructor