I am trying to mock static method using powermock.
Below is my code:
public class Helper{
public static User getLoggedInUser(HttpServletRequest request) throws NotFoundException {
String access = request.getHeader("Authorization");
if(access == null || access.isEmpty()) {
throw new Exception("Access is null");
}
User user = new User();
return user;
}
}
And this is the controller function from where i am calling the static method getUser:
#RequestMapping(value = "user/userInfo/{Id}", method = RequestMethod.GET, headers = "Accept=application/json")
public #ResponseBody
ResultDTO getUser(#PathVariable("Id") Integer Id, HttpServletRequest request) throws NotFoundException, UnauthorizedException {
Integer userID = -1;
User user = Helper.getLoggedInUser(request);
if(user != null){
userID = user.getUserId();
}
//do something
}
And this is my test class:
//#RunWith(PowerMockRunner.class)
//#PrepareForTest(Helper.class)
public class CustomerControllerNGTest {
#InjectMocks
private userController instance = new PaymentCustomerController();
public PaymentCustomerControllerNGTest() {
}
#BeforeClass
public void setUpClass() throws Exception {
}
#AfterClass
public static void tearDownClass() throws Exception {
}
#BeforeMethod
public void setUpMethod() throws Exception {
try{
MockitoAnnotations.initMocks(this);
}catch(Exception ex){
System.out.println(ex.getMessage());
}
try{
mockMvc = MockMvcBuilders.standaloneSetup(instance).build();
// mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}catch(Exception ex){
System.out.println(ex.getMessage());
}
}
#AfterMethod
public void tearDownMethod() throws Exception {
}
#Test
public void testGetUserInfo() throws Exception {
User user = new User();
user.setUserId(1234);
HttpServletRequest request = mock(HttpServletRequest.class);
//this is for the static method
PowerMockito.mockStatic(Helper.class);
**PowerMockito.when(Helper.getLoggedInUser(request)).thenReturn(user);**
//do something
}
}
Now whenever i am executing the test case, and whenever it is executing the lone marked with bold, it is going inside the static method and throwing the exception "Access is null" rather than mocking the method , it is executing the method. Any idea?
I also tried by uncommenting these lines:
//#RunWith(PowerMockRunner.class)
//#PrepareForTest(Helper.class)
but still same exception.
Thanks
Try to uncomment:
//#RunWith(PowerMockRunner.class)
//#PrepareForTest(Helper.class)
and use
Mockito.when(Helper.getLoggedInUser(request)).thenReturn(user);
I wrote blog post on topic, that contain links to working examples on GitHub. These use TestNg instead of JUnit, but this shouldn't matter.
EDIT
I would suggest to always use latest combination of Mockito and PowerMock available. Older combinations were often pretty buggy with confusing errors. Current latest combination is Mockito 1.9.5-rc1+, PowerMock 1.5+. Pre-1.5 versions of PowerMock wasn't Java7 compliant.
Related
I have been creating a project with Aspect Oriented Programming paradigm and
I have an "ExceptionLogAspect" class attribute which is used on business methods to log the errors throwing from them.
public class ExceptionLogAspect : MethodInterception
{
private readonly LoggerServiceBase _loggerServiceBase;
private static byte _risk;
public ExceptionLogAspect(Type loggerService, byte risk)
{
if (loggerService.BaseType != typeof(LoggerServiceBase))
{
throw new System.Exception(AspectMessages.WrongLoggerType);
}
_loggerServiceBase = (LoggerServiceBase)Activator.CreateInstance(loggerService);
_risk = risk;
}
protected override void OnException(IInvocation invocation, System.Exception e)
{
var logDetailWithException = GetLogDetail(invocation);
logDetailWithException.ExceptionMessage = e.Message;
_loggerServiceBase.Error(logDetailWithException);
}
}
This Aspect migrates MethodInterception class that I created with Castle.DinamicProxy package. And OnException method included by MethodInterception logs the exception data.
public abstract class MethodInterception:MethodInterceptionBaseAttribute
{
protected virtual void OnBefore(IInvocation invocation){}
protected virtual void OnAfter(IInvocation invocation){}
protected virtual void OnException(IInvocation invocation, System.Exception e){}
protected virtual void OnSuccess(IInvocation invocation){}
public override void Intercept(IInvocation invocation)
{
var isSuccess = true;
OnBefore(invocation);
try
{
invocation.Proceed();//Business Method works here.
}
catch (Exception e)
{
isSuccess = false;
OnException(invocation, e);
throw;
}
finally
{
if(isSuccess)
OnSuccess(invocation);
}
OnAfter(invocation);
}
}
When I run the code and try-catch block doesn't work for Exception. So catch block isn't called and no messages are logged.
If I turn the business method into a syncronous method, exception will be thrown and data will be logged.
How can I solve this asynchronous method problem?
I tried this solution, it works properly.
Intercept method has to be like this to make this process asynchronous.
Otherwise, this method doesn't work properly for async.
There are some other ways, for example Castle CoreAsync Interceptor, you can find it on Github or NuGet.
https://github.com/JSkimming/Castle.Core.AsyncInterceptor
public override void Intercept(IInvocation invocation)
{
var isSuccess = true;
OnBefore(invocation);
try
{
invocation.Proceed(); //Metodu çalıştır
if (invocation.ReturnValue is Task returnValueTask)
{
returnValueTask.GetAwaiter().GetResult();
}
if (invocation.ReturnValue is Task task && task.Exception != null)
{
throw task.Exception;
}
}
catch (Exception e)
{
isSuccess = false;
OnException(invocation, e);
throw;
}
finally
{
if (isSuccess)
OnSuccess(invocation);
}
OnAfter(invocation);
}
I am trying to implement Rest Assured framework with cucumber
I am facing a weird scenario that I have defined all my step definitions of my feature file then also I am getting error as below when I run my feature file:-
Step undefined
You can implement this step and 3 other step(s) using the snippet(s) below:
#Given("I create new service by using create service API data")
public void i_create_new_service_by_using_create_service_api_data() {
// Write code here that turns the phrase above into concrete actions
throw new io.cucumber.java.PendingException();
}
and When I run the same from Junit Testrunner then I get error as below :-
INFO net.serenitybdd.rest.decorators.request.RequestSpecificationDecorated - No BaseStepListener, POST /services not registered.
In my framework I am defining basepackage containing base class file which is as below :-
public class TestBase {
public static Properties propertyConfig = new Properties();
public static FileInputStream fis;
public static Response response;
public static RequestSpecification requestSpecification;
public static void loadPreConfigs(){
try {
fis = new FileInputStream("./src/test/resources/ConfigurationURLs/config.properties");
try {
propertyConfig.load(fis);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
RestAssured.baseURI=propertyConfig.getProperty("BaseURI");
}
}
Then I have a ApiCall package which contains all class files which have request specification and respective response storing rest API calls
The APICall file is given below:-
public class PostRequestCall extends TestBase {
private static String productVal;
public static int getProductVal() {
return Integer.parseInt(productVal);
}
public static void setProductVal(String productVal) {
PostRequestCall.productVal= productVal;
}
public RequestSpecification definePostRequest(){
requestSpecification= SerenityRest.given();
requestSpecification.contentType(ContentType.JSON);
return requestSpecification;
}
public Response CreateService(String serviceName){
JSONObject jsonObject=new JSONObject();
jsonObject.put("name",serviceName);
response=definePostRequest().body(jsonObject).post(propertyConfig.getProperty("createService"));
return response;
}
}
Then I have step file which are the class file in which I define the steps of serenity given below:
public class PostRequestSteps {
PostRequestCall postRequestCall=new PostRequestCall();
#Step
public RequestSpecification setPostSpecification(){
TestBase.requestSpecification=postRequestCall.definePostRequest();
return TestBase.requestSpecification;
}
#Step
public Response setPostRequestCall(String serviceName){
TestBase.response=postRequestCall.CreateService(serviceName);
return TestBase.response;
}
}
And I have defined a package which contains all the step definition classes one such class is as below :-
public class PostRequest_StepDefinitions {
String serviceID;
#Steps
PostRequestSteps postRequestSteps=new PostRequestSteps();
#Before
public void setUp() {
TestBase.loadPreConfigs();
}
#Given("I create new service by using create service API data")
public void i_create_new_service_by_using_create_service_api_data() {
postRequestSteps.setPostSpecification();
}
#When("I provide valid name {string} for service creation")
public void i_provide_valid_name_for_service_creation(String serviceName) {
TestBase.response=postRequestSteps.setPostRequestCall(serviceName);
}
#And("I save the id of created service")
public void i_save_the_id_of_created_service() {
serviceID=TestBase.response.jsonPath().get("id").toString();
PostRequestCall.setProductVal(serviceID);
}
#Then("I validate status code {int}")
public void i_validate_status_code(int statusCode) {
Assert.assertEquals(TestBase.response.getStatusCode(),statusCode);
}
The Junit Runner file and feature files are below
I'm trying to use HangFire to call an action method on a class. From the code below, the action method works correctly if called outside of HangFire, but throws an exception when using HangFire. I also tried using Invoke() as stated by other similar posts.
Expression body should be of type
'MethodCallExpression'(Parameter'methodCall')'
I'd like to figure out how to have HangFire execute this type of method if possible.
class Program
{
static void Main(string[] args)
{
var a = new ActionTest();
// Calling this method prints out Hello World correctly
a.DoAction();
GlobalConfiguration.Configuration.UseSqlServerStorage(#"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Test;Integrated Security=True");
// Call this method from HangFire produces exception: Expression body should be of type 'MethodCallExpression'(Parameter'methodCall')'
BackgroundJob.Enqueue<ActionTest>(a => a.DoAction());
}
}
public class ActionTest
{
public ActionTest()
{
DoAction = WriteHello;
}
public Action DoAction;
public void WriteHello()
{
Console.WriteLine("Hello World");
}
}
I don't see any other way than wrapping the call to DoAction in a genuine method :
public class ActionTest
{
public ActionTest()
{
DoAction = WriteHello;
}
public Action DoAction;
public void InvokeAction()
{
DoAction();
}
public void WriteHello()
{
Console.WriteLine("Hello World");
}
}
then
BackgroundJob.Enqueue<ActionTest>(a => a.InvokeAction());
I am using one MVC application where i have to handle all exception occurs in the code. I have found about exception filter and implemented there. Below is the created exception filter code:
public class HandleException : HandleErrorAttribute
{
#region Log Initialization
FileLogService logService = new
FileLogService(typeof(HandleException));
#endregion
public override void OnException(ExceptionContext filterContext)
{
filterContext.ExceptionHandled = true;
Log(filterContext.Exception);
base.OnException(filterContext);
}
private void Log(Exception exception)
{
logService.Error(exception.ToString());
}
}
Now i used this filter as attribute in my controller like below:
[AuthSession]
[HandleException]
public class OrganizationalController : BaseController
{
public ActionResult OrgSummary()
{
try
{
int a = 1, b = 0;
int result = a / b;
}
catch (Exception ex)
{
throw ex;
}
ViewData["ShowGrid"] = false;
return View();
}
}
As you can see in above code i am trying to generate exception in the code. In catch exception block when i used throw keyword then exception filter getting executed else not.
Now i need here when any exception occurs in the application i need to show a custom popup message for user. In popup message once user click on ok button then user should be available on the same page. The page should not break or get blank.
How could i implement this functionality?
Try this code. May be it helps
public class MyExceptionFilter: FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
// below code will redirect to the error view
filterContext.Result = new RedirectResult("ErrorPage.html");
filterContext.ExceptionHandled = true;
}
}
and then you need to apply the above as an attribute to your action methods like:
[MyExceptionFilter]
public ActionResult XYZ()
{
}
I have a class(looks something like this) I'm trying to test.
#Component
#Path("/user")
#Produces(MediaType.APPLICATION_JSON)
public class UserResource extends BaseResource {
#Autowired UserService userService;
#POST
#Path("register")
public User registerUser(User user){
...
User registeredUser = userService.register(user);
...
return registeredUser;
}
}
The test looks like this.
public class UserResourceTest {
#Tested UserResource userResource;
#Injectable UserService userService;
#Mocked BaseResource baseResource;
#Test
public void registerShouldDoSomething(){
User user = new User();
final User registerResult = new User();
...
new NonStrictExpectations() {{
userService.register((User)any); result = registerResult;
}};
userResource.registerUser(user);
...
}
}
For some reason in the tested class, userService is null and throwing a NPE when register is called on it (UserService is a class not interface/abstract btw). I'm wondering if perhaps some of the annotations(javax or Spring) may be clashing with JMockit or something(Although I've tried removing them)?
I've tried switching the injectable to just #Mocked, and I've tried removing it and having it be a #Mocked test method param. Nothing seems to be solving the NPE.
I had the same issue, the problem was mixing Spring annotations - Autowired with Java Resource. If you mix them only Java will be injected.
For more details please take a look at:
mockit.internal.expectations.injection.InjectionPoint
mockit.internal.expectations.injection.FieldInjection
especially discardFieldsNotAnnotatedWithJavaxInjectIfAtLeastOneIsAnnotated method.
This is a dirty solution to the problem:
package mockit.internal.expectations.injection;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class DirtyHack {
static {
try {
setFinalStatic(InjectionPoint.class.getDeclaredField("WITH_INJECTION_API_IN_CLASSPATH"), false);
} catch (Exception e) {
e.printStackTrace();
}
}
static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
}
Then your test need to for example extends this class.
I ended up using reflection to manually set the #Injectable fields in the #Tested class
public class UserResourceTest {
#Tested UserResource userResource;
#Injectable UserService userService;
#Mocked BaseResource baseResource;
#Test
public void registerShouldDoSomething(){
Deencapsulation.setField(userResource,userService); //This line
User user = new User();
final User registerResult = new User();
...
new NonStrictExpectations() {{
userService.register((User)any); result = registerResult;
}};
userResource.registerUser(user);
...
}
}
Still not sure what the bug is, but this works for me