Mock an object inside a method in JUnit - unit-testing

I'm trying to get to grips with JUnit & Mockito etc.
I currently have a method with the below line.
ObjectMetadata metadata = getMetadata(path.toString());
Is there any way I can mock it? I've tried things like the below
Whitebox.setInternalState(<mock of class>, "metadata", "abc");
but I just get
org.powermock.reflect.exceptions.FieldNotFoundException: No instance field named "metadata" could be found in the class hierarchy of com.amazonaws.services.s3.model.ObjectMetadata.
I think it's because previous use of Whitebox.setInternalState was with variables.
Any info. that might get me started would be appreciated.

If the method is protected then you dont need to use Powermockito, plain vanilla Mockito is enough and spying would do the trick here. Assuming the test class is in the same package as the production one, just in the src/test/java dir.
ClassUnderTest classUnderTestSpy = Mockito.spy(new ClassUnderTest()); // spy the object
ObjectMetadata objectMetadataToReturn = new ObjectMetadata();
doReturn(objectMetadataToReturn).when(classUnderTestSpy).get(Mockito.any(String.class));
I used any() matcher for the input but you can use a concrete value also.
Update If you cannot see the method then you would need to create an inner class that extends the prod one, implement the get method:
public class Test{
ObjectMetadata objectMetadataToReturn = new ObjectMetadata();
#Test
public void test(){
ClassUnderTestCustom classUnderTestCustom = new ClassUnderTestCustom();
// perform tests on classUnderTestCustom
}
private class ClassUnderTestCustom extends ClassUnderTest{
#Override
public String getMetadata(String path){
return objectMetadataToReturn ;
}
}
}

#PrepareForTest(ObjectMetadata.class)
public class PowerMockDemoTest {
private ObjectMetadata objectMetadata;
#Before
public void setUp() {
objectMetadata = new ObjectMetadata();
}
#Test
public void testMockNew() throws Exception {
ObjectMetadata mockObjectMetadata = mock(ObjectMetadata.class);
PowerMockito.whenNew(ObjectMetadata.class)
.withAnyArguments().thenReturn(mockObjectMetadata);
ObjectMetadata actualObjectmetadata = getMetadata(path.toString());
assertThat(actualObjectmetadata, is(mockObjectMetadata));
}
}

Related

How can I use MockWebServer for Junit test cases of webclient?

I have a spring-boot application which calls some third party URL (let's say http://example.com/someUri) using webclient(I have used application-dev.properties for injecting this url in my application to achieve loose coupling) and consumes the response and use it in my application.
It's my first time when I am going to write test cases for webclient. and there I used #SprintBootTest.
I found that there are two ways where I can test my webclient with third party Api call by mocking the api call and make it call to my local url(which will be using url(http://localhost:{portNumber}/someUri) from my testing properties file: src/test/resources/application.properties) where It will be giving some mockedResponse in return to my real client:
Using wiremock
Using MockWebServer
consider above code for better understanding:
#Service
Class SampleService{
#Value("${sample.url}")
private String sampleUrl;
public String dummyClient() {
String sample =webClient.get()
.uri(sampleUrl)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.retrieve()
.bodyToMono(String.class)
.block();
return sample;
}
}
application-dev.properties:
sample.url:http://example.com/someUri
src/test/resouces/application.properties:
http://localhost:8090/someUri
Testing class:
#SpringBootTest
public class sampleTestingClass {
#Autowired
private SampleService sampleService;
#Value("${sample.url}")
private String sampleUrl;
public static MockWebServer mockWebServer = new MockWebServer();
#BeforeAll
static void setUp() throws IOException {
mockWebServer.start(8090);
}
#AfterAll
static void tearUp() throws IOException {
mockWebServer.close();
}
HttpUrl url = mockWebServer.url("/someUri");
mockWebServer
.enqueue(
new MockResponse()
.setResponseCode(200)
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.setBody("Sample Successful"));
String sample = sampleService.dummyClient();
assertEquals(sample ,matches("Sample Successful"));
}
}
but this code isn't working. it's giving me above error:
java.lang.NullPointerException
It will be really helpful if anybody knows how this can be fixed to achieve my unit testing using mocked Url? Thanks in advance!
Here is a working example:
#Component
public class QuotesClient {
private final WebClient webClient;
public QuotesClient(WebClient.Builder builder, #Value("${client.baseUrl}") String baseUrl) {
this.webClient = builder.baseUrl(baseUrl).build();
}
public JsonNode getData() {
return this.webClient
.get()
.retrieve()
.bodyToMono(JsonNode.class)
.block();
}
}
Using the WebClient.Builder is optional.
The corresponding test can look like the following:
class QuotesClientTest {
private QuotesClient quotesClient;
private MockWebServer server;
#BeforeEach
public void setup() {
this.server = new MockWebServer();
this.quotesClient = new QuotesClient(WebClient.builder(), server.url("/").toString());
}
#Test
public void test() {
server.enqueue(new MockResponse()
.setStatus("HTTP/1.1 200")
.setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}")
.addHeader("Content-Type", "application/json"));
JsonNode data = quotesClient.getData();
assertNotNull(data);
System.out.println(data);
}
}
If you are searching for a similar setup using WireMock, Spring Boot, and JUnit 5, take a look at the linked guide.

***HELP*** Test/Mock: Service Class using Rest Template, Response and HTTP Entities, Exceptions

I have a service class, with for readability purpose, I have provided the code with dummy variables and objects. I am trying to write a JUNIT test class for the service, primarily with Mockito. No matter how hard I try, I am not able to hit the method serviceMethod irrespective of using spy/mock. I have also included a test, following the main class.
I know I am missing something here, but doesn't cross my mind. I need an eye to review this and let me know how I can write a proper test class for this and obtain coverage for the method.
(P.S. all the necessary imports are in-place and not pasted here to keep this concise)
Thanks in advance!
#Service
public class ServiceClass {
private static final Logger LOGGER = LoggerFactory.getLogger(ServiceClass.class);
#Autowired
String stringUrl;
RestTemplate restTemplate = new RestTemplate();
public void serviceMethod(ModelObject model) {
try {
HttpEntity<ModelObject> request = new HttpEntity<>(model);
ResponseEntity<String> response = restTemplate.exchange(stringUrl,
HttpMethod.POST, request, String.class);
LOGGER.info(response.getBody() + "and " + response.getStatusCode());
} catch (HttpClientErrorException exception) {
LOGGER.info(exception.getResponseBodyAsString());
} catch (HttpStatusCodeException exception) {
LOGGER.info(exception.getResponseBodyAsString());
}
}
Sample Test:
#RunWith(MockitoJUnitRunner.Silent.class)
public class ServiceClassTest {
#InjectMocks
private ServiceClass serviceClass;
#Mock
private RestTemplate restTemplate;
#Test
public void testServiceMethod() {
ServiceClass spy = Mockito.spy(serviceClass);
// ServiceClass spy = mock(ServiceClass.class, Mockito.CALLS_REAL_METHODS);
doNothing().when(spy).serviceMethod(Mockito.any(ModelObject.class));
Mockito.doCallRealMethod().when(spy).serviceMethod(Mockito.any(ModelObject.class));
ResponseEntity<String> responseEntity = new ResponseEntity<>(HttpStatus.ACCEPTED);
Mockito.when(restTemplate.exchange(ArgumentMatchers.anyString(), ArgumentMatchers.any(HttpMethod.class),
ArgumentMatchers.<HttpEntity<ModelObject>>any(), ArgumentMatchers.<Class<String>>any()))
.thenReturn(responseEntity);
}

How to test POST method in Spring boot using Mockito and JUnit

I am newbie to Unit testing using JUnit and Mockito in Spring boot framework.
I want to test this method. How to test POST Request method:
// add Employee
#RequestMapping(method = RequestMethod.POST)
public void addEmployee(#RequestBody Employee employee){
this.employeeService.addEmployee(employee);
}
Thank you in advance
As #merve-sahin rightly pointed out, you can use #WebMvcTest to achieve this.
Look at the following example :
#RunWith(SpringRunner.class)
#WebMvcTest(YourController.class)
public class YourControllerTest {
#Autowired MockMvc mvc;
#MockBean EmployeeService employeeService;
#Test
public void addEmployeeTest() throws Exception {
Employee emp = createEmployee();
mvc.perform(post("/api/employee")
.contentType(MediaType.APPLICATION_JSON)
.content(toJson(emp)))
.andExpect(status().isOk());
}
}
In Above code you can mock your dependent service using #MockBean.
The test will perform post on your custom Employee object and validate the response
You can add headers, authorization while calling perform
Assuming you using JSON as media type, you can write toJson() method using any json library to convert Employee object into Json string format
private String toJson(Employee emp) {
If you are using XML, then you can do the same for XML
You can validate the response using expectations in chained way.
As rightly pointed out, please checkout MockedMvc link which should help you
Go through this following example:
#RunWith(SpringJUnit4ClassRunner.class)
public class ApplicationControllerTest {
#Mock
EmployeeService employeeService;
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
initMocks(this);
YourController controller = new YourController(employeeService);
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
#Test
public void addEmployee() throws Exception {
Employee emp = new Employee("emp_id","emp_name");//whichever data your entity class have
Mockito.when(employeeService.addEmployee(Mockito.any(Employee.class))).thenReturn(emp);
mockMvc.perform(MockMvcRequestBuilders.post("/employees")
.content(asJsonString(emp))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json;charset=UTF-8"));
}
public static String asJsonString(final Object obj) {
try {
return new ObjectMapper().writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
In above given example mock your service class which is required to post the data to your Employee entity class.
I'm assuming that you're doing this via controller so you first need to initialize the controller which comes under the #Before annotation.
By doing above example you'll be able to post your data into the JSON format.
The below example is using JUnit5, Mockito3.x, spring-boot2.4.4, and
assertj3.x
The spring-boot-starter-test dependency from version 2.2.0
already comes with Junit 5 and contains also Hamcrest, assertj, and Mockito libraries.
In JUnit 5, “Runner” extension points, available in JUnit 4, are replaced by the Extension API.
You can register the Mockito extension via #ExtendWith.
Initializes mocks annotated with #Mock annotation so that explicit usage of MockitoAnnotations#initMocks(Object) is not required.
From spring-boot 2.1, there is no need to load the SpringExtension using annotation #ExtendWith because it's included as a meta-annotation in these annotations #DataJpaTest, #WebMvcTest, and #SpringBootTest.
Complete example with Github link: https://github.com/jdamit/DemoSpringBootApp.git
**#WebMvcTest(controllers = UserController.class)**
public class UserControllerTest {
#Autowired
private MockMvc mockMvc;
#Autowired
private ObjectMapper mapper;
#MockBean
private UserServiceImpl userService;
private List<UserDto> users;
private UserDto user;
private String URI = "/users";
#BeforeEach
void setUp(){
users = List.of(new UserDto("Amit", "Kushwaha", "jdamit2027#gmail.com", "sector 120"),
new UserDto("Amit", "Kushwaha", "jdamit2027#gmail.com", "sector 120"),
new UserDto("Amit", "Kushwaha", "jdamit2027#gmail.com", "sector 120"));
user = new UserDto("Rahul", "Swagger", "rahul.swagger#gmail.com", "sector 120");
}
#Test
//#Disabled
void getUsersTest() throws Exception {
Mockito.when(userService.getUsers()).thenReturn(users);
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get(URI)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
Assertions.assertThat(result).isNotNull();
String userJson = result.getResponse().getContentAsString();
Assertions.assertThat(userJson).isEqualToIgnoringCase(mapper.writeValueAsString(users));
}
#Test
//#Disabled
void createUserTest() throws Exception {
Mockito.when(userService.createUser(Mockito.any(UserDto.class))).thenReturn(user);
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post(URI)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsString(user).getBytes(StandardCharsets.UTF_8))
.accept(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
Assertions.assertThat(result).isNotNull();
String userJson = result.getResponse().getContentAsString();
Assertions.assertThat(userJson).isNotEmpty();
Assertions.assertThat(userJson).isEqualToIgnoringCase(mapper.writeValueAsString(user));
}
}

gwt junit for testing objectify

I am trying to test my gwt app with gwt junit but seems to not be able to set up things correctly to make the objectify be tested.
All the tutorials demonstrate testing DataStore but not objectify (which is higher level of data base service)
My base class for testing looks like this:
public class TestBase {
private static final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
protected static ObjectifyFactory fact;
#BeforeClass
public static void setUp() {
helper.setUp();
fact = new ObjectifyFactory() {
#Override
public Objectify begin(ObjectifyOpts opts)
{
opts.setSessionCache(false);
return super.begin(opts);
}
};
}
#AfterClass
public static void tearDown() {
helper.tearDown();
}
}
then i have classes that extends the base:
public class UserServiceTest extends TestBase{
private User inactiveUser;
private UserService us;
Objectify _ofy;
#Rule
public ExpectedException thrown = ExpectedException.none();
#Before
public void beforeTest() {
//Register the classes used in the test
fact.register(User.class);
us = new UserService();
inactiveUser = new User();
}
#Test
public void basicTest(){
Objectify ofy = ObjectifyService.begin();
ofy.put(inactiveUser); //This fails with exception: An exception occurred: com.google.apphosting.api.ApiProxy$CallNotFoundException
//My goal is to reach these test but "addUser" uses also objectify
//UserService.addUser("shpungin#gmail.com", "bye");
//assertNotNull(inactiveUser.get_id());
}
Do you have an idea of what am I doing wrong? I looked all over the Internet and found no solution (some even said to remove app-engine-sdk from .classpath but it dosent seems to work.
Thank you.
I solved this.
Although com.google.apphosting.api.ApiProxy should be part of the app-engine
Some jars still needs to be inside the .classpath :
${SDK_ROOT}/lib/testing/appengine-testing.jar
${SDK_ROOT}/lib/impl/appengine-api.jar
${SDK_ROOT}/lib/impl/appengine-api-labs.jar
${SDK_ROOT}/lib/impl/appengine-api-stubs.jar //This one I missed
Also I upgraded my app-engine to v 1.6.4.1 (maybe that also helped).

How to use JUnit with EJB3 and JPA

I'm trying to test my Session Beans with JUnit, but I can't. I've tried a lot of method, but still get some exceptions.
Here is what I need:
I have a few Stateless Session Beans I need to test. Each has the same #PersistenceContext and uses an EntityManager
With my test cases I need to test their methods. For instance: if I add an user with username X and then I try to add another one with the same username, I want to catch an Exception.
Can someone provide a simple and short generic test example? I've already read many, but I always get an error (I get NullPointerException for the EntityManager when I call a method like: sessionBean.method() (which does, for instance, entityManager.find(...)), or I am not able to initialize the Context, or other PersistenceException).
You might be interested in one of the latest posts of Antonio Goncalves:
WYTIWYR : What You Test Is What You Run
It tells about testing EJB with EntityManager using:
Mockito,
Embedded EJB Container,
Arquillian.
I solved creating a Stateless Session Bean and injecting its Entity Manager to test classes. I post the code in case someone will need it:
#Stateless(name = "TestProxy")
#Remote({TestProxyRemote.class})
public class TestProxy implements TestProxyRemote {
#PersistenceContext(unitName = "mph")
private EntityManager em;
#Override
public void persist(Object o) {
em.persist(o);
}
#Override
public void clear() {
em.clear();
}
#Override
public void merge(Object o) {
em.merge(o);
}
#Override
#SuppressWarnings({ "rawtypes", "unchecked" })
public Object find(Class classe, String key) {
return em.find(classe, key);
}
#Override
#SuppressWarnings({ "rawtypes", "unchecked" })
public Object find(Class classe, long key) {
return em.find(classe, key);
}
#SuppressWarnings("rawtypes")
#Override
public List getEntityList(String query) {
Query q = em.createQuery(query);
return q.getResultList();
}
}
public class MyTest {
#BeforeClass
public static void setUpBeforeClass() throws NamingException {
Properties env = new Properties();
env.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
env.setProperty(Context.PROVIDER_URL, "localhost:1099");
env.setProperty("java.naming.factory.url.pkgs","org.jboss.naming:org.jnp.interfaces");
jndiContext = new InitialContext(env);
try {
proxy = (TestProxyRemote) jndiContext.lookup("TestProxy/remote");
} catch (NamingException e) {
e.printStackTrace();
}
}
}
Then I can use proxy.find() to get the entities I need, o proxy.getEntityList() to execute a query to retrieve all the instance of an Entity. Or I can add other methods if I want.
Unitils provides a really cool support for JPA. Unitils can be used with JUnit or TestNG and in case you need a mocking framework, Unitils provides its own mocking module as well as support for EasyMock.
#JpaEntityManagerFactory(persistenceUnit = "testPersistenceUnit")
#DataSet(loadStrategy = RefreshLoadStrategy.class)
public class TimeTrackerTest extends UnitilsTestNG {
#TestedObject
private TimeTrackerBean cut = new TimeTrackerBean();
#InjectInto(target="cut",property="em")
#PersistenceContext
private EntityManager em;
#Test
#DataSet("TimeTrackerTest.testAddTimeSlot.xml")
public void yourTest() {
...
}
}
#JpaEntityManagerFactory - Used to specify your persistence unit. It automatically picks up the persistence.xml from your project classpath.
#DataSet - Just in case you need to load any test data you can use this.
#TestedObject - Marks your Class Under Test
#PersistenceContext - Automatically creates your EntityManager instance from the configurations made in the persistence.xml - PersistenceUnit.
#InjectInto - Injects the em instance into the target (cut)
For more information refer this.
Hope this helps.
I'm using Needle for this. It works well with Mockito and EasyMock if you want to mock other objects.
First I write a persistencte.xml for tests (src/test/resources/META-INF) like this:
<persistence-unit name="rapPersistenceTest" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:~/test"/>
...
</properties>
</persistence-unit>
In my Junit-Testclass I write:
public class DaoNeedleTest {
//here Needle will create persistenceContext for your testclass
public static DatabaseRule databaseRule = new DatabaseRule("rapPersistenceTest");
//here you can get the entityManager to manipulate data directly
private final EntityManager entityManager = databaseRule.getEntityManager();
#Rule
public NeedleRule needleRule = new NeedleRule(databaseRule);
//here you can instantiate your daoService
#ObjectUnderTest
DAOService daoService;
#Test
public void test() {
//if your method needs a transaction here you can get it
entityManager.getTransaction().begin();
daoService.yourMethod();
entityManager.getTransaction().commit();
}
You also need a Needle-configuration File in src/test/resources, where you tell what kind of Mock-provider you are using. E.g. I'm using Mockito:
mock.provider=de.akquinet.jbosscc.needle.mock.MockitoProvider
That's it.