I have a method in OneServiceImpl class as follows. In that class I am calling an interface method from another class.
public class OneServiceImpl {
//created dependency
final private SecondService secondService;
public void sendMessage(){
secondService.validateAndSend(5)
}
}
public interface SecondService() {
public Status validateAndSend(int length);
}
public class SecondServiceImpl {
#Override
public Status ValidateAndSend(int length) {
if(length < 5) {
throw new BadRequestException("error", "error");
}
}
}
Now when I am try to perform unit test on OneServiceImpl I am not able to throw a BadRequestException.
when(secondService.validateAndSend(6)).thenThrow(BadRequestException.class);
Not quite sure what your use case is, but I think you should write an own test to accept and test an exception.
#Test(expected = BadRequestException.class)
public void testValidateAndSend(){
SecondService secondService = new SecondService();
secondservice.ValidateAndSend(6); //method should be lowercase
}
Not sure this is the case considering you didn't post a full example of code + unit tests, but your mock will throw only when you are passing 6 as parameter. When configuring the behaviour of your mock with when you are telling it to throw only when the validateAndSend method is called with parameter 6.
when(secondService.validateAndSend(6)).thenThrow(...)
In your code you have 5 hardcoded. So that mock will never throw for the code you have, because it's configured to react to an invocation with parameter 6 but the actual code is always invoking it passing 5.
public void sendMessage(){
secondService.validateAndSend(5)
}
If the value passed to the mock is not important you could do something like the following, that will throw no matter what's passed to it:
when(secondService.validateAndSend(any())).thenThrow(BadRequestException.class);
On the other hand, if the value is important and it has to be 5 you could change the configuration of your mock with:
when(secondService.validateAndSend(5)).thenThrow(BadRequestException.class)
Related
I'm unit testing a Spring boot web app with Mockito. One of my methods is returning a void, but if I try to test it, I get compilation errors.
This is the test I wrote:
public void testDeleteActor()throws NetflixException {
when(actorRepository.findById(1L)).thenReturn(Optional.of(Mockito.any(Actor.class)));
assertEquals(null, service.deleteActorById(Mockito.anyLong());
}
And this is the method I'm trying to test:
#Override
public void deleteActorById(Long id) throws NetflixException {
Actor actor = actorRepository
.findById(id)
.orElseThrow(() -> new NotFoundException("Actor id not found - " + id));
actorRepository.delete(actor);
}
As you can see in the following screenshot, I'm getting an error with my assertEquals() statement:
In your code, your method isn't actually returning null, it's returning nothing (void). That means that you can't write assertions based on what the method returns. This is the reason why the assertEquals() statement is giving you an error.
In stead of testing what the method returns, you can test the expected behaviour of the method. In this example, there are three things we expect:
The method should retrieve the actor by its ID.
The method should throw an exception if no actor was found with the given ID.
The method should delete the actor if it was found.
To implement this these tests, you can use Mockito's verify() and AssertJ's assertThatExceptionOfType(). For example:
#Test
void deleteActorById_retrievesActorByID() {
Actor actor = new Actor();
when(actorRepository.findById(1L)).thenReturn(Optional.of(actor));
service.deleteActorById(1L);
verify(repository).findById(1L);
}
#Test
void deleteActorById_throwsExceptionIfIDNotFound() {
assertThatExceptionOfType(NotFoundException.class)
.isThrownBy(() -> service.deleteActorById(1L))
.withMessage("Actor id not found - 1");
}
#Test
void deleteActorById_deletesActorIfIDFound() {
Actor actor = new Actor();
when(actorRepository.findById(1L)).thenReturn(Optional.of(actor));
service.deleteActorById(1L);
verify(actorRepository).delete(actor);
}
I want to log Controller and the rest of packages differently. I know I can use 2 separate methods for this but these 2 methods are very similar, so I want to add a code to check that would look something like this
#Around("controllerPoint() || theRest()")
public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
if( called from controllerPoint() ) {
execute this short section of code # (1)
}
// rest of code
What would this code be like?
Also, if after I execute (1) and I want to pass a variable to this same method again when it executes for other packages, how can I do it?
you can invoke the method like the below which will return your method name
joinPoint.getSignature().getName()
You could get method name, from join point:
#Aspect
#Configuration
public class TrackingConfig {
#Around("execution(* your.package.Controller.*(..))")
public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
String methodName = pjp.getSignature().getName();
if ("theRest".equals(methodName)) {
System.out.println("AROUND! theRest ");
} else if ("controllerPoint".equals(methodName)) {
System.out.println("AROUND! controllerPoint ");
}
return pjp.proceed();
}
}
I've been looking on internet but haven't found the solution if any (new on UnitTest and Mockito)
It's possible to test a method that return a call of a service and manipulate it's result before to return it? Example;
public Observable<Reports> getUserReports(Integer userId) {
return serviceClient
.getReports(userId)
.flatMap(serviceReports -> {
System.out.println("Testing inside flatMap"); <- never reach this line therefore duno if methods down here are invoked and work perfectly
final Observable<List<Report>> reports = getPendingReports(userId, serviceReports);
//More methods that modify/update information
return zip(observable1, observable2, observable3
(report1, report2, report3) -> {
updateReports(otherArguments, report1, report2, report3);
return serviceReports;
});
});
}
So far I've tried;
#Test
public void myTest(){
when(serviceClient
.getReports(anyInt()))
.thenReturn(Observable.just(reports));
Observable<Reports> result = mocketClass.getUserReports(userId)
}
Tryed with Spy and Mock but no luck so far. Any hint or help would be great.
To mock getReports() behavior you need to mock the serviceClient firstly and pass it into your service class.
Just as example:
#Test
public void myTest(){
// Given
final ServiceClient mockedServiceClient = Mockito.mock(ServiceClient.class);
when(mockedServiceClient
.getReports(anyInt()))
.thenReturn(Observable.just(reports));
// and create an instance of your class under testing with injected mocked service client.
final MyUserService userService = new MyUserService();
userService.setServiceClient(mockedServiceClient);
// When run a method under test
Observable<Reports> actualResult = userService.getUserReports(userId)
// Then
// actualResult to be verified.
}
I have a simple scenario in which am trying to verify some behavior when a method is called (i.e. that a certain method was called with given parameter, a function pointer in this scenario). Below are my classes:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
AppBootStrapper bootStrapper = context.getBean(AppBootStrapper.class);
bootStrapper.start();
}
}
#Component
public class AppBootStrapper {
private NetworkScanner networkScanner;
private PacketConsumer packetConsumer;
public AppBootStrapper(NetworkScanner networkScanner, PacketConsumer packetConsumer) {
this.networkScanner = networkScanner;
this.packetConsumer = packetConsumer;
}
public void start() {
networkScanner.addConsumer(packetConsumer::consumePacket);
networkScanner.startScan();
}
}
#Component
public class NetworkScanner {
private List<Consumer<String>> consumers = new ArrayList<>();
public void startScan(){
Executors.newSingleThreadExecutor().submit(() -> {
while(true) {
// do some scanning and get/parse packets
consumers.forEach(consumer -> consumer.accept("Package Data"));
}
});
}
public void addConsumer(Consumer<String> consumer) {
this.consumers.add(consumer);
}
}
#Component
public class PacketConsumer {
public void consumePacket(String packet) {
System.out.println("Packet received: " + packet);
}
}
#RunWith(JUnit4.class)
public class AppBootStrapperTest {
#Test
public void start() throws Exception {
NetworkScanner networkScanner = mock(NetworkScanner.class);
PacketConsumer packetConsumer = mock(PacketConsumer.class);
AppBootStrapper appBootStrapper = new AppBootStrapper(networkScanner, packetConsumer);
appBootStrapper.start();
verify(networkScanner).addConsumer(packetConsumer::consumePacket);
verify(networkScanner, times(1)).startScan();
}
}
I want to verify that bootStrapper did in fact do proper setup by registering the packet consumer(there might be other consumers registered later on, but this one is mandatory) and then called startScan. I get the following error message when I execute the test case:
Argument(s) are different! Wanted:
networkScanner bean.addConsumer(
com.spring.starter.AppBootStrapperTest$$Lambda$8/438123546#282308c3
);
-> at com.spring.starter.AppBootStrapperTest.start(AppBootStrapperTest.java:24)
Actual invocation has different arguments:
networkScanner bean.addConsumer(
com.spring.starter.AppBootStrapper$$Lambda$7/920446957#5dda14d0
);
-> at com.spring.starter.AppBootStrapper.start(AppBootStrapper.java:12)
From the exception, clearly the function pointers aren't the same.
Am I approaching this the right way? Is there something basic I am missing? I played around and had a consumer injected into PacketConsumer just to see if it made a different and that was OK, but I know that's certainly not the right way to go.
Any help, perspectives on this would be greatly appreciated.
Java doesn't have any concept of "function pointers"; when you see:
networkScanner.addConsumer(packetConsumer::consumePacket);
What Java actually compiles is (the equivalent of):
networkScanner.addConsumer(new Consumer<String>() {
#Override void accept(String packet) {
packetConsumer.consumePacket(packet);
}
});
This anonymous inner class happens to be called AppBootStrapper$$Lambda$7. Because it doesn't (and shouldn't) define an equals method, it will never be equal to the anonymous inner class that the compiler generates in your test, which happens to be called AppBootStrapperTest$$Lambda$8. This is regardless of the fact that the method bodies are the same, and are built in the same way from the same method reference.
If you generate the Consumer explicitly in your test and save it as a static final Consumer<String> field, then you can pass that reference in the test and compare it; at that point, reference equality should hold. This should work with a lambda expression or method reference just fine.
A more apt test would probably verify(packetConsumer, atLeastOnce()).consumePacket(...), as the contents of the lambda are an implementation detail and you're really more concerned about how your component collaborates with other components. The abstraction here should be at the consumePacket level, not at the addConsumer level.
See the comments and answer on this SO question.
How can I use two action compositions in Play Framework 2.4 (in Java)?
Suppose that, to avoid code duplication, I've got two actions to use :Auth and LogData.
How can I use both in an action composition?
This won't compile, causing a duplicate annotation error:
# play.PlayExceptions$CompilationException: Compilation error[error:
duplicate annotation]
#play.db.jpa.Transactional()
#With(Auth.class)
#With(LogData.class)
public static Result callForumTeacher(String random, Long gameId){
//Action code
return ok(Json.toJson("data"));
}
This is a skeleton on how Auth and LogData are implemented:
public class CheckPausedGame extends Action.Simple {
#Override
public F.Promise<Result> call(Http.Context context) throws Throwable {
if (checkCondition(context)) {
return delegate.call(context);
} else {
F.Promise<Result> promise = F.Promise.promise(new F.Function0<Result>() {
#Override
public Result apply() throws Throwable {
return redirect("/paused");
}
});
return promise;
}
}
}
This only a skeleton omitting some methods not useful for this question.
While the documentation doesn't seem to clearly state this (at least I haven't found it anywhere), the intended way to use #With in cases like this is to pass all Actions at once (With takes an array)
Your code becomes
#play.db.jpa.Transactional()
#With(value = {Auth.class, LogData.class})
public static Result callForumTeacher(String random, Long gameId){
//Action code
return ok(Json.toJson("data"));
}
See the api doc