delete method in junit test with spring mvc - java

I'm making junit test for spring mvc project, I can make test method for get and post methods like the following example for get method,now I need to make test for delete method put I got this error
(The method DELETE(String, Long) is undefined for the type myclassTest)
this tutorial use delete with no error
http://www.petrikainulainen.net/programming/spring-framework/integration-testing-of-spring-mvc-applications-rest-api-part-one/
#Test
public void testGetOne() throws Exception {
ResultActions perform = mockMvc.perform(get(
MachineWebservice.URL+"/{id}",1)
);
perform.andDo(print())
.andExpect(status().isOk())
;
}

You simply haven't statically imported the member (the static delete method declared within MockMvcRequestBuilders). Because of this, the compiler thinks that the method should exist in the class it's used in, myclassTest, which obviously isn't the case.
Add the appropriate import statement to your test class
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;

Related

How can I pass a dynamic parameter-that I will create with some random library- in testNg xml?

I want to pass a dynamic parameter to a test case from testng xml, my parameter is something like:
String dynamicParameter=generateRandomStringForMail();
Here is my testcase:
#Test()
public void customerCreatorAllProducts () throws Exception {
setup();
Functions.pages.LoginPage login = PageFactory.initElements(driver, Functions.pages.LoginPage.class);
login.navigateRegisterPage().createFixedPasswordCustomerRequiredFields(dynamicParameter);
}
I will be using this parameter in other cases as well, how can i do this from testng.xml or with something else?
I am not familiar with testing.xml, but Mockito immediately comes to mind for this: http://mockito.org.
add Mockito to your project (e.g. through the build.gradle page)
add the import to your test file:
import static org.mockito.Mockito.*;
within your test class, create a mock of the class which has the generateRandomStringForMail() method. In my current project, I have
DefaultFileService mockFileService = mock(DefaultFileService.class);
define what you want the method to return under these test conditions, e.g.
when(mockFileService.generateRandomFileName()).thenReturn("fileName");
Whenever your tests need to use the result of the method in question, you can use "fileName", because you have told the test environment to give this response. My project has a method to update the image file associated with an inventory item, which process includes using the DefaultFileService to generate a random file name, then passing the image file and the new file name to the DefaultFileService to save the file in the system. My test code can't see or guess what file name would actually be produced, but my 'when' line above has resolved that problem for the purposes of testing my QuiltController class:
quiltController.update(data, mockFile);
verify(mockFileService).save(mockFile, "fileName"); // confirms the save() method was called with the expected parameters
It feels pretty similar to what you are trying to do, so hopefully that helps you proceed if you do want to explore Mockito. Don't be surprised if you need to refactor some of your work to make it more testable. I did, and have better code as a result. Give it a go :)

How to mock System.exit with PowerMockito?

I want to unit test Java code that calls System.exit(-1) and want it to just do nothing instead of exiting the process. The underlying reason is that otherwise JaCoCo does not work properly and project guidelines want to see that line covered. Changing the tested code is not an option, too. Other calls to System should work normally. PowerMockito 2.0.7 is already used in the project and should be used here, too. My current Java version is 1.8.0_181 on Windows.
I tried with
PowerMockito.spy(System.class);
PowerMockito.doNothing().when(System.class, "exit", ArgumentMatchers.any(int.class));
//here comes the code under test that calls System.exit
It does not seem to work, System.exit seems to exit the process anyway.
How do it get this to work?
I think you should replace both the lines in your sample code
PowerMockito.spy(System.class);
PowerMockito.doNothing.....
to
PowerMockito.mockStatic(System.class);
This change works in my local as System.exit does nothing because of the mock on static method.
Also, I hope you are using PrepareForTest annotation
#PrepareForTest(CLASS_UNDER_TEST)
The spy method is to call real methods and have some wrapper around the non-static methods. Since you need a mock for static methods, mockStatic method should be used instead.
Update 1
The PowerMockito mockStatic method by default creates mock for all the static methods within the class. I don't have any clean solution. But, I can suggest a solution which looks ugly but does what is needed i.e only mock specific static method and remaining methods are invoking real methods. PoweMockito's mockStatic method is internally calling DefaultMockCreator to mock the static methods.
#RunWith(PowerMockRunner.class)
public class StaticTest {
#Test
public void testMethod() throws Exception {
// Get static methods for which mock is needed
Method exitMethod = System.class.getMethod("exit", int.class);
Method[] methodsToMock = new Method[] {exitMethod};
// Create mock for only those static methods
DefaultMockCreator.mock(System.class, true, false, null, null, methodsToMock);
System.exit(-1); // This will be mocked
System.out.println(System.currentTimeMillis()); // This will call up real methods
}
}
As per the PowerMockito documentation, the right way to call static void method is -
PowerMockito.mockStatic(SomeClass.class);
PowerMockito.doNothing().when(SomeClass.class);
SomeClass.someVoidMethod();
Reference - https://github.com/powermock/powermock/wiki/Mockito#how-to-stub-void-static-method-to-throw-exception
This should create the mock behaviour for the specific static void method. Unfortunately, this doesn't work for System Class because System class is final. Had it been not final, this would have worked. I tried it and I got this exception -
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class java.lang.System
Mockito cannot mock/spy because :
- final class
Code -
#Test
public void testMethod() throws Exception {
PowerMockito.mockStatic(System.class);
PowerMockito.doNothing().when(System.class);
System.exit(-1); // mockito error coming here
System.exit(-1);
System.currentTimeMillis();
}

Mock inner method which uses local variable as paramenter

I've recently started using Mockito 3 + Junit 5 + Spring 5 and I'm writing some example tests in order to understand how Mockito works. I have a question about inner calls. So, I have a spring component A in which is injected some DAO component someObjectDAO. The A class:
#Component("aClass")
public class A {
#Autowired
private ObjectDAO someObjectDAO;
public Long countRecords() {
ObjectSearchCriteria search = new ObjectSearchCriteria();
return someObjectDAO.count(search);
}
}
I want to test A's countRecords method. I've mocked and injected someObjectDAO like this:
#ExtendWith(MockitoExtension.class)
#ContextConfiguration("contextConfFileSomewhere")
public class ATest {
#Mock
ObjectDAO someObjectDAOMock;
#InjectMocks
A aComponent;
#Test
void testCount() {
ObjectSearchCriteria search = Mockito.mock(ObjectSearchCriteria.class);
Mockito.when(someObjectDAOMock.count(search)).thenReturn(1L);
Assertion.assertEquals(1L, aComponent.countRecords());
}
}
But this way is incorrect, in fact PotentialStubbingProblem is raised.
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'count' method:
someObjectDAO.count(
com.example.java.ObjectSearchCriteria#45cc6b13
);
-> at com.example.java.A.countRecords()
- has following stubbing(s) with different arguments:
1. someObjectDAOMock.count(
Mock for ObjectSearchCriteria, hashCode: 204078646
);
Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
However, there are legit scenarios when this exception generates false negative signal:
- stubbing the same method multiple times using 'given().will()' or 'when().then()' API
Please use 'will().given()' or 'doReturn().when()' API for stubbing.
- stubbed method is intentionally invoked with different arguments by code under test
Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).
For more information see javadoc for PotentialStubbingProblem class.
If I understand correctly the exception indicates that I'm passing an object different from the actual object used in the code under test, right?
So, how can I mock a inner method which uses a local variable as parameter?
You want to mock the call to ObjectDAO.count which has parameters. Instead of passing an instance of the expected parameter as an argument, you should use an argument matcher:
Mockito.when(someObjectDAOMock.count(Mockito.any(ObjectSearchCriteria.class)))
.thenReturn(1L);
Edit: You should probably never even want to "mock a local variable". Your goal is to test the system under test (countRecords method) without knowing implementation details. All you can do is mock the dependencies.

How to make the unit test execute a particular test case everytime when it sees a certain function in the executing java project?

I am having a build failure issue while running a bunch of unit test over a java project. I am getting the NoClassDefFoundError which is happening because of the lack of ability for the unit test to get the dependencies. I am trying to mock an object for the class and then call the function, but the code is structured in a way that is getting a bit complex for me to handle the issue. I am very new to unit testing. I have provided below, a sample of code structure that my project has
Class ServiceProvider(){
obj declarations;
public void mainFunction(){
//Does a couple of things and calls a function in another class
boolean val = subFunction();
}
public boolean subFunction(){
boolean val = AnotherClass.someFunction(text);
//this function throws lots of exceptions and all those are caught and handled
return val;
}
#RunsWith(MockitoJUnitRunner.class)
Class UnitTestBunch(){
#Mock
AnotherClass acObj = new AnotherClass();
#InjectMock
ServiceProvider sp = new ServiceProvider();
#Test
public void unitTest1() throws Exception{
when(acObj.someFunction(text)).thenReturn(true);
}
#Test
public void unitTest2() throws Exception{
thrown.expect(ExceptionName.Class);
sp.mainFunction();
}
I have a test that uses the mock object and performs the function call associated with that class. But, the issue here is that there are a bunch of other unit test cases that are written similar to the unitTest2 function and calls the mainFunction at the end of the test. This mainFunction invokes someFunction() and causes NoCalssDefFoundError(). I am trying to make the unit test execute the content in unitTest1 everytime when it sees the AnotherClass.someFunction(). I am not sure if this is achievable or not. There could be another better way to resolve this issue. Could someone please pitch in some ideas?
In your test you seem to be using unitTest1 for setup, not for testing anything. When you run a unit test, each test should be able to run separately or together, in any order.
You're using JUnit4 in your tests, so it would be very easy to add the statement you have in unitTest1 into a #Before method. JUnit4 will call this method before each test method (annotated with #Test).
#Before
public void stubAcObj() throws Exception{
when(acObj.someFunction(text)).thenReturn(true);
}
The method may be named anything, though setUp() is a common name borrowed from a method to override in JUnit3. However, it must be annotated with org.junit.Before.
If you need this from multiple test cases, you should just create a helper, as you would with any code. This doesn't work as well with #InjectMocks, but you may want to avoid using #InjectMocks in general as it will fail silently if you add a dependency to your system-under-test.
public class AnotherClassTestHelper {
/** Returns a Mockito mock of AnotherClass with a stub for someFunction. */
public static AnotherClass createAnotherClassMock() {
AnotherClass mockAnotherClass = Mockito.mock(AnotherClass.class);
when(mockAnotherClass.someFunction(text)).thenReturn(true);
return mockAnotherClass;
}
}
As a side note, this is a counterintuitive pattern:
/* BAD */
#Mock
AnotherClass acObj = new AnotherClass();
You create a new, real AnotherClass, then instruct Mockito to overwrite it with a mock (in MockitoJUnitRunner). It's much better just to say:
/* GOOD */
#Mock AnotherClass acObj;

Mockito re-stub method already stubbed with thenthrow

I ran into a problem with mockito.
I am developing a web application. In my tests the user management is mocked.
There are some cases when I have to alter the User returned by the getLoggedInUser() method.
The problem is, that my getLoggedInUser() method can also throw an AuthenticationException.
So when I try to switch from no user to some user, the call to
when(userProvider.getLoggedInUser()).thenReturn(user);
throws an exception, as userProvider.getLoggedInUser() is already stubbed with thenTrow()
Is there any way for to tell the when method not to care about exceptions?
Thanks in advance - István
In new Mockito versions you can use stubbing consecutive calls to throw exception on first can and returning a value on a second call.
when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException())
.thenReturn("foo");
https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#10
My first reaction to your question is that it sounds like you are trying to do too much in one test.
For ease of testing and simplicity each test should test one thing only. This is the same as the Single Responsibility Principle. I often find programmers trying to test multiple things in one test and having all sorts of problems because of it. So each of your unit test methods should follow this flow:
Setup a single scenario for the test.
Make a call to the class being tested to trigger the code being tested.
Verify the behaviour.
So in your case I would expect to see at least two tests. One where getLoggedInUser() returns a user, and one where getLoggedInUser() throws an exception. That way you will not have problems with trying to simulate different behaviour in the mock.
The second thought that spring to mind is not to stub. Look into using expect instead because you can setup a series of expectation. I.e. the first call returns a user, the second call throws an exception, the third call returns a different user, etc.
Is there any way for to tell the when method not to care about exceptions?
To actually answer this question:
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
public class MyTest {
#Test
public void testA() {
// setup
ArrayList<Object> list = mock(ObjectArrayList.class);
when(list.indexOf(any())).thenReturn(6);
when(list.indexOf(any())).thenReturn(12);
// execute
int index = list.indexOf(new Object());
// verify
assertThat(index, is(equalTo(12)));
}
#Test
public void testB() {
// setup
ArrayList<Object> list = mock(ObjectArrayList.class);
when(list.add(any())).thenThrow(new AssertionError("can't get rid of me!"));
when(list.add(any())).thenReturn(true);
// execute
list.add(new Object());
}
#Test
public void testC() {
// setup
ArrayList<Object> list = mock(ObjectArrayList.class);
when(list.add(any())).thenThrow(new AssertionError("can't get rid of me!"));
Mockito.reset(list);
when(list.add(any())).thenReturn(true);
// execute
list.add(new Object());
}
/**
* Exists to work around the fact that mocking an ArrayList<Object>
* requires a cast, which causes "unchecked" warnings, that can only be suppressed...
*/
class ObjectArrayList extends ArrayList<Object> {
}
}
TestB fails due to the assert that you can't get rid of. TestC shows how the reset method can be used to reset the mock and remove the thenThrow command on it.
Note that reset doesn't always seem to work in some more complicated examples I have. I suspect it might be because they're using PowerMockito.mock rather than Mockito.mock?
Use Mockito.reset() to reset any particular mocks, for example Mockito.reset(mock1, mock2)
Check for more detail: https://stackoverflow.com/a/68126634/12085680
For example:
#Test
void test() {
when(mock.someMethod(any())).thenThrow(SomeException.class);
// Using a service that uses the mock inside for example
assertThrows(SomeException.class, () -> service.someMethodThatUsesTheMock("test"));
Mockito.reset(mock); // reset it so you can reuse that mock on another test
}

Categories