Is there any valid variant to test controller with the predicate in it?
#RestController
public class QueryLauncherController {
private QueryLauncherService queryLauncherService;
#Autowired
public QueryLauncherController(QueryLauncherService queryLauncherService) {
this.queryLauncherService = queryLauncherService;
}
#GetMapping("/queryLauncher/CMP")
public List<QueryLauncherDto> getLaunchersCompany(RTAdmin admin) {
return queryLauncherService.getLaunchersList(admin, QueryLauncher::getIsCompany);
}
}
I've tried to solve this issue using any(Predicate.class) but IDE highlights it as Unchecked assignment and it looks pretty dumb.
The code I've written for the test is:
public void returnCompanyLinks_When_companyRequested() throws Exception {
when(queryLauncherService.getLaunchersList(eq(user), any(Predicate.class))).thenReturn(queryLauncherDtos);
mockMvc.perform(get(QUERY_LAUNCHER_URL + CMP).session(mockSession))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(content().json(new Gson().toJson(queryLauncherDtos)));
}
The goal is to run method only in the case when QueryLauncher::getIsInvestor.
List<QueryLauncherDto> getLaunchersList(RTAdmin admin, Predicate<QueryLauncher> launcherType);
Are there any variants to do it?
I believe this will do what you want:
doReturn(queryLauncherDtos).when(queryLauncherService).getLaunchersList(eq(user),
ArgumentMatchers.<Predicate<QueryLauncher>>anyObject());
Some caveats:
I prefer the doReturn(value).when(mock).method form when specifying mocked functionality,
but it is easy enough to flip to the when(mock.method).thenReturn(value) form.
anyObject is deprecated in the latest version of Mockito.
It is still present,
but it is deprecated.
Edit: I read the 2.23 release Mockito documentation,
and it mentions that anyObject is just an alias for the any method.
The following should work and is not deprecated:
doReturn(queryLauncherDtos).when(queryLauncherService).
getLaunchersList(eq(user),
ArgumentMatchers.<Predicate<QueryLauncher>>any());
Related
Currently, I am working on the sample demo application for learning purposes, in which I have implemented the CRUD operations for the Tutorial.
Here is my sample code to create a new tutorial:
TutorialsController.java
public class TutorialsController {
#Autowired
TutorialService tutorialService;
#PostMapping("/tutorials")
public ResponseEntity<Tutorial> createTutorial(#RequestBody Tutorial tutorial) {
try {
Tutorial _tutorial = tutorialService.createTutorial(tutorial);
return new ResponseEntity<>(_tutorial, HttpStatus.CREATED);
} catch (Exception | BaseException e) {
logger.info("Error:: {}", e.getMessage());
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
TutorialServiceImpl.java
#Service
public class TutorialServiceImpl implements TutorialService {
public Tutorial createTutorial(Tutorial tutorial) {
If(Utility.checkToggle) {
throw new BadRequestException("Validation faild for given tutorial. Please check provided parameters")
} else {
return tutorialRepository.save(
new Tutorial(tutorial.getTitle(), tutorial.getDescription(), tutorial.getAuthor(), false)
);
}
}
}
I have a static method checkToggle in the Utility class which performs some toggle check and if the given check gets failed I am raising BadRequestException.
Now I am trying to test the scenario where the toggle check is failed. Here is my sample code
#RunWith(PowerMockRunner.class)
#PrepareForTest({TutorialsController.class})
public class TutorialsControllerTest {
#InjectMocks
TutorialsController tutorialsController;
#Mock
TutorialServiceImpl tutorialServiceImpl;
#Test
public void test1() {
Tutorial tutorial = new Tutorial();
tutorial.setAuthor("Test");
tutorial.setDescription("Test");
PowerMockito.mockStatic(Utility.class);
when(Utility.checkToggle()).thenReturn(true);
ResponseEntity<Tutorial> response = tutorialsController.createTutorial(tutorial);
assertEquals(response.getStatusCode(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
But my test case is failing. After debugging found that Utility.checkToggle() method is not getting mocked.
So can you please let me know why this is happening? And how to fix this.
For implementing the test case I followed https://ngdeveloper.com/how-to-test-controller-using-powermock-in-spring-boot/ tutorial.
You need to specify Utility.class in the list of the #PrepareForTest annotations parameters.
On the other hand, the class under test (TutorialsController.class) should not be listed there, as you probably don't want PowerMock to manipulate its bytecode - otherwise you will not test the "real thing".
Btw: Don't know if you use that, but since Mockito 3.4.0 also mocking of static methods is possible, see this answer on SO
This question already has answers here:
How do I get Mockito mocks to cause a failure when unexpected calls are made?
(4 answers)
Closed 1 year ago.
I'm trying to understand if I can do the following in mockito.
Let's say I have this class:
class PersonService {
public NameResolver resolver;
public String getFullName(Person person) {
// ...
String firstName = resolver.getFirstName(person);
// ...
String lastName = resolver.getLastName(person);
// ...
return firstName + lastName;
}
}
And have a test for this class:
class PersonServiceTest {
private PersonService underTest;
#Test
void test() {
NameResolver mock = mock(NameResolver.class);
PersonService underTest = new PersonService(mock);
when(mock.getFirstName()).thenReturn("first-name");
underTest.getFullName();
}
}
The thing is, that I have unstabbed resolver.getLastName(person) method and mockito will stub this with default value ("" in case of String, I guess). What I'd like to do is to throw exception every time I call method of the mock that no stub attached. There is a framework named mockk in Kotlin ecosystem which behaves like this and this feature makes you write really reliable unit tests and it is pretty convinient after all.
I saw Answers class in mockito and it looks like this behaviour is configurable but I spend pretty much time looking for an answer on the web and suprisingly found nothing.
Moreover I saw that I can make mockito throw exceptions in case there are mocks that are not in use, but didn't found if I can make this option a default one, like via config file or something like this.
Create the mock with a default answer:
NameResolver mock =
mock(
NameResolver.class,
invocation -> { throw new UnsupportedOperationException(); });
This answer will only be invoked for otherwise-unstubbed methods.
I have currently this the issue that there is an object of Type CoolObj created within my method doSomething().
This object goes through some processes and at the end I want to verify if everything is ok and then continue.
Now the problem is that I cannot control the behavior and prevent an exception to be thrown.
Either hasErros() should return false or I kind of mute the verify method. But I could not figure out how.
Any idea how to solve this issue please?
public class ExampleClass {
public void doSomething(){
CoolObj coolObj = new CoolObj();
verify(coolObj);
}
private void verify(CoolObj coolObj) {
if(coolObj.hasErrors()){
throw new Exception(); //this is my issue
}
}
}
Basically, the problem that you have is related to the fact, that test doesn't control creation of CoolObj instances (that's because ExampleClass is not designed in testable way).
The best approach would be to change the design of ExampleClass, for example by delegating creating CoolObj instances to corresponding factory. Then mock instance created by factory and setup needed responses of hasErrors by Mockito.
However, if for some reason you are forced to leave the design of ExampleClass as is, then you can use PowerMock to mock construction of new instances.
For the code snippet provided in the question, following is an example of tests with and without exception thrown:
#RunWith(PowerMockRunner.class)
#PrepareForTest(ExampleClass.class)
public class ExampleClassTest {
private final ExampleClass exampleClass = new ExampleClass();
#Test
public void exceptionIsNotThrownIfCoolObjHasNoErrors() throws Exception {
CoolObj coolObjMock = Mockito.mock(CoolObj.class);
PowerMockito.whenNew(CoolObj.class).withNoArguments().thenReturn(coolObjMock);
Mockito.when(coolObjMock.hasErrors()).thenReturn(false);
Assertions.assertThatCode(exampleClass::doSomething)
.doesNotThrowAnyException();
}
#Test
public void exceptionIsThrownIfCoolObjHasErrors() throws Exception {
CoolObj coolObjMock = Mockito.mock(CoolObj.class);
PowerMockito.whenNew(CoolObj.class).withNoArguments().thenReturn(coolObjMock);
Mockito.when(coolObjMock.hasErrors()).thenReturn(true);
Assertions.assertThatThrownBy(exampleClass::doSomething)
.isInstanceOf(RuntimeException.class);
}
}
Notes:
For more details, regarding code snippet in the answer take a look here.
Please, note that to work properly PowerMock and Mockito should have compatible versions.
I need to write unit tests against a pre-existing code base using TestNG, Mockito and now PowerMockito, to test private and static methods more easily. I am currently trying to write a test against a private void method in a class that we are testing, but am unable to figure it out. In the normal PowerMock API there are methods called replayAll(), verifyAll(), and expectLastCalled(), which are suitable for most purposes. I just can't find good docs that explain how to do it the PowerMockito way. Any explanations or insights on this would be much appreciated.
Method to test:
private void pVMethod(Type param) throws Exception {
param.setA(StaticClass.methodA().toString());
param.setB(StaticClass.methodB().toString());
// getMemo(String label) is in a public class in same package
param.setC(getMemo("memo.provider"));
param.setD(getMemo("memo.item"));
try {
param.setTimestamp(DataTypeFactory.newInstance().newXMLGregorianCalendar(newjava.util.GregorianCalendar()));
} catch (SomeException e) {
...
throw new Exception();
}
}
test attempt:
#Test(expectedExceptions = Exception.class)
public void pVMethod() throws Exception {
TestClass testMock = mock(TestClass.class);
Exception exception = mock(Exception.class);
// StaticClass staticClassMock = mock(StaticClass.class); ??
mockStatic(StaticClass.class);
// when(..) and thenReturn(..) are static imports from PowerMockito library
when(StaticClass.methodA()).thenReturn("stubStringA");
when(StaticClass.methodB()).thenReturn("stubStringB");
doThrow(exception).when(param).setTimestamp(Mockito.any(XMLGregorianCalendar.class));
// Docs say method name can be inferred via reflection
Whitebox.invokeMethod(tested, event);
// this is where things are hairy. testedSpy is defined at the top level
verifyPrivate(testedSpy).pVMethod(testMock);
}
Ok, here is the answer:
In PowerMockito, if you want to verify the behavior of a private void method you use the verifyPrivate() method, but you have to do it like this:
verifyPrivate(tested).invoke("privateMethodName", argument);
Notice the use of the invoke method, missing from the last line of the OP.
NOTE: You do not have to use a doNothing().when(mock.privateMethod()) statement, because void methods in mock objects don't do anything by default.
example taken from here
Its being a few months since I am working with java legacy code, this are some of the things I am dealing with:
0% test coverage.
Huge functions in occasions I even saw some with more than 300 lines of code.
Lots of private methods and in occasions static methods.
Highly tight coupled code.
At the beginning I was very confused, I found difficult to use TDD in the legacy. After doing katas for weeks and practicing my unit testing and mocking skills, my fear has decreased and I feel a bit more confident. Recently I discovered a book called: working effectivelly with legacy, I didn't read it, I just had a look at the table of contents and I discovered something that is new for me, The Seams. Apparently this is very important when working in the legacy.
I think that this Seams could help me alot in breaking dependencies and make my code testeable so I can increase the code coverage and make my unit testing more precise.
But I have a lot of doubts:
Can somebody explain me the difference between a seam and a mock?
Do Seams, break TDD rules in what regards not touching production code, before is tested?
Could you show me some simple example that compares a Seam and a Mock?
Below I would like to paste an example I did today where I tried to break a dependency with the goal of making the code testeable and finally increasing test coverage. I would appreciate if you could comment a bit if you see some mistakes?
This is how the legacy code looked like at the beginning:
public class ABitOfLegacy
{
private String sampleTitle;
String output;
public void doSomeProcessing(HttpServletRequest request) {
String [] values = request.getParameterValues(sampleTitle);
if (values != null && values.length > 0)
{
output = sampleTitle + new Date().toString() + values[0];
}
}
}
If I just add a unit test that calls that method and asserts that variable output, has a certain value after the call,then I would be making a mistake, because I am not unit testing, I would be doing integration testing. So what I need to do, Is get rid of the dependency I have in the parameter. To do So, I replace the parameter with an interface:
public class ABitOfLegacy
{
private String sampleTitle;
String output;
public void doSomeProcessing(ParameterSource request) {
String [] values = request.getParameters(sampleTitle);
if (values != null && values.length > 0)
{
output = sampleTitle + new Date().toString() + values[0];
}
}
}
This is how the interface looks like:
public interface ParameterSource {
String[] getParameters(String name);
}
The next thing I do, is create my own implementation of that interface but I include the HttpServletRequest as a global variable and I implement the method of the interface using the method/s of HttpServletRequest:
public class HttpServletRequestParameterSource implements ParameterSource {
private HttpServletRequest request;
public HttpServletRequestParameterSource(HttpServletRequest request) {
this.request = request;
}
public String[] getParameters(String name) {
return request.getParameterValues(name);
}
}
Until this point, I think that all the modifications on the production code were safe.
Now I create the Seam in my test package. If I understood well, now I am able to safely change the behavoir of the Seam. This is how I do it:
public class FakeParameterSource implements ParameterSource {
public String[] values = {"ParamA","ParamB","ParamC"};
public String[] getParameters(String name) {
return values;
}
}
And the final step, would be to get support from the Seam, to test the original behavoir of the method.
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import code.ABitOfLegacyRefactored;
import static org.hamcrest.Matchers.*;
public class ABitOfLegacySpecification {
private ABitOfLegacy aBitOfLegacy;
private String EMPTY = null;
#Before
public void initialize() {
aBitOfLegacy = new ABitOfLegacy();
}
#Test
public void
the_output_gets_populated_when_the_request_is_not_empty
() {
FakeParameterSource fakeParameterSource = new FakeParameterSource();
aBitOfLegacy.doSomeProcessing(fakeParameterSource);
assertThat(aBitOfLegacy.output,not(EMPTY));
}
#Test(expected=NullPointerException.class)
public void
should_throw_an_exception_if_the_request_is_null
() {
aBitOfLegacy.doSomeProcessing(null);
}
}
This will give me 100% test coverage.
I appreciate your thoughts:
Did I break the dependency correctly?
Are the unit tests missing something?
What could be done better?
Is this example good enough to help me understand the difference between a Seam and a Mock?
How could a mock help me here if I don't use the Seam?
A seam is a place in the code that you can insert a modification in behavior. You created a seam when you setup injection of your dependency.
One way to take advantage of a seam is to insert some sort of fake. Fake's can be hand-rolled, as in your example, or be created with a tool, like Mockito.
So, a mock is a type of fake, and a fake is often used by taking advantage of a Seam.
As for your tests and the way you broke the dependency, that's pretty much how I would have done it.
Seams
A seam is a place that allows you to modify the behavior without modifying the code.
In your example, the following is an example of an Object seam (if i'm not mistaken). It allows you to pass in a different object without having to change the code. hence it is a type of seam.
public void doSomeProcessing(ParameterSource request) {..}
By making the parameter an abstract type (instead of a concrete class), you have introduced a seam. The seam now allows you to modify the behavior of the method without editing its code - i.e. at the place of invokation, I can pass in a different object and make the method do something else.
Mocks
Now instead of creating your custom fake (creating a subtype of the interface), you could using a Mock framework to do something like this
Mocks also support asserting whether specific methods were called on it, argument matching and other nifty functionality to be consumed by tests. Less test code to maintain. Mocks are primarily used to assert that a specific call is being made to a dependency. In your example, you seem to be in need of a Stub, you just want to return a canned value.
Pardon my rusty JMock..
#Test
public void
the_output_does_not_get_populated_when_the_request_is_empty
() {
Mockery context = new Mockery();
final ParameterSource mockSource = context.mock(ParameterSource.class)
context.checking(new Expectations(){{
oneOf(mockSource).getParameters();
will(returnValue(new string[]{"ParamA","ParamB","ParamC"} );
}});
aBitOfLegacy.populate(mockSource);
assertThat(aBitOfLegacy.output,not(EMPTY));
}
in .Net
var mockSource = new Mock<ParameterSource>();
mockSource.Setup(src => src.GetParameters())
.Returns(new []{"ParamA","ParamB","ParamC"});