I try to create a Junit test, the probleme is that I get the exception:
Caused by: java.lang.NullPointerException at com.liferay.portal.kernel.cache.key.CacheKeyGeneratorUtil.getCacheKeyGenerator(CacheKeyGeneratorUtil.java:56)
the program can't instantiate the the CacheKeyGenerator -cause the defaultCacheKeyGenerator is already null!! this latter can be instantiated when PortalContextLoaderListener.contextInitialized(ServletContextEvent servletContextEvent) is called... but I'm not using PortalContextLoaderListener ... is there any way to solve this probleme
depending on what you're about to test, my advice is typically an additional level of indirection. If you need something that depends on larger infrastructure to be initialized, like in this case, it's not a proper unit test any more, rather a larger integration test.
Adding an indirection to get the cache-key should suffice. At runtime you can hook that component up to Liferay, at testing time, you return your testing values, that could be constants, random results or whatever you need for your test.
Related
Getting following exceptions when run all tests together but works as expected when executed individually
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced or misused argument matcher detected here
java.lang.NullPointerException: Cannot invoke "[Ljava.lang.Class;.clone()" because ".parameterTypes" is null
Please check whether you have mocked java.lang.reflect.Method (or any java reflection types) in one of your test classes?
use getClass().getMethod() like approach to get it done instead of mocking relect types becasue java not allows to do that.
Springboot: I got a mocked service and a method needs to return a javax.validation.ConstraintViolationException in order to properly unit test the caller class.
I cannot seem to find a way to generate a ConstraintViolationException or ConstraintViolation for that matter in Hibernate Validators.
Is there some solution I missing out?
Thank you
What do you want to achieve exactly?
Because you can create a ConstraintViolationException without any violations in it if you just need the exception.
If you want a violation in it (you just have to pass a set of violations to the constructor), I would say you have several possibilities:
You can simply implement ConstraintViolation as it's an interface and just put some code where you see fit.
Otherwise, I would trigger a real validation (with Validator.validate(myBean)) and get the violations from there.
You can use ConstraintViolationImpl#forBeanValidation() to forge a violation but it's an internal class so it might break in future versions of HV.
Easymock 3.5.1
JUnit 4.12
Maven 3.5.0
Intellij Build #IU-181.5281.24, built on June 12, 2018
I have a unit test and contained within this unit test is my problem method:
#Test(expected = CheckoutException.class)
public void performCheckout_CheckoutException() throws Exception {
// setup test data
Order order = new OrderImpl();
OMSOrder omsOrder = new OMSOrderImpl();
Order omsOrderProxy = OMSOrderProxy.proxify(order, omsOrder, Logger.getRootLogger());
omsOrderProxy.setId(1L);
FulfillmentOrder fulfillmentOrder = new FulfillmentOrderImpl();
FulfillmentGroup fulfillmentGroup = new FulfillmentGroupImpl();
fulfillmentGroup.setType(FulfillmentType.DIGITAL);
fulfillmentOrder.setFulfillmentGroup(fulfillmentGroup);
((OMSOrder)omsOrderProxy).getAllFulfillmentOrders().add(fulfillmentOrder);
ProcessContext<CheckoutSeed> context = new DefaultProcessContextImpl<>();
// create the expected flow
expect(orderService.save(anyObject(Order.class), eq(false))).andReturn(order).times(2);
replay(orderService);
expect((ProcessContext<CheckoutSeed>)checkoutWorkflow.doActivities(anyObject(CheckoutSeed.class))).andReturn(context);
replay(checkoutWorkflow);
expect(fulfillmentService.fulfill(anyObject(FulfillmentOrder.class))).andThrow(new FulfillmentException());
replay(fulfillmentService);
// test
checkoutService.performCheckout(omsOrderProxy);
// check results
verify(orderService);
verify(checkoutWorkflow);
verify(fulfillmentService);
}
orderService is a strict mock (defined in a #Before setup method):
orderService = createStrictMock(OrderService.class);
Each and every unit test class that uses this orderService creates this mock (whether strict or nice) in this #Before setup method.
Running this test method in Intellij (right-click, Run ...) achieves a successful result. Running the test at class level, again right-click, Run ... achieves another successful result. A mvn clean install (whether in Intellij or at the command line) renders the following error:
java.lang.Exception: Unexpected exception, expected<org.curtiscommerce.core.checkout.service.exception.CheckoutException> but was<java.lang.IllegalStateException>
at org.easymock.internal.ExpectedInvocation.createMissingMatchers(ExpectedInvocation.java:52)
at org.easymock.internal.ExpectedInvocation.<init>(ExpectedInvocation.java:41)
at org.easymock.internal.RecordState.invoke(RecordState.java:51)
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:40)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:94)
at com.sun.proxy.$Proxy27.save(Unknown Source)
at com.central.core.checkout.service.TestCheckoutServiceImpl.performCheckout_CheckoutException(TestCheckoutServiceImpl.java:151)
Line 151 (detailed in the code line directly above) relates to:
expect(orderService.save(anyObject(Order.class), eq(false))).andReturn(order).times(2);
which is a line in this method.
Now to get the exception details I remove the 'expected' attribute from the #Test annotation and the exception thrown is clearer:
java.lang.IllegalStateException: 2 matchers expected, 12 recorded.
This exception usually occurs when matchers are mixed with raw values when recording a method:
foo(5, eq(6)); // wrong
You need to use no matcher at all or a matcher for every single param:
foo(eq(5), eq(6)); // right
foo(5, 6); // also right
at org.easymock.internal.ExpectedInvocation.createMissingMatchers(ExpectedInvocation.java:52)
at org.easymock.internal.ExpectedInvocation.<init>(ExpectedInvocation.java:41)
at org.easymock.internal.RecordState.invoke(RecordState.java:51)
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:40)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:94)
at com.sun.proxy.$Proxy27.save(Unknown Source)
at com.central.core.checkout.service.TestCheckoutServiceImpl.performCheckout_CheckoutException(TestCheckoutServiceImpl.java:151)
Also, when I run a suite of tests in Intellij say at the level of the package where my unit test class resides (com.central.core.checkout.service), I get this same error. I have removed all other versions of easymock in .m2/repository to ensure there is no conflict.
The concern is; why does this error only occur upon a mvn clean install (in Intellij or cmd line) and at a package level unit test run?
I suppose what really concerns me, aside from differing results depending on how the test is run, is the the exception that is thrown:
java.lang.IllegalStateException: 2 matchers expected, 12 recorded.
tells me there are 2 matchers and 12 recorded. Is this including those created in other unit tests, almost as if spanning a test session? I find this difficult to believe as each unit test method creates a fresh mock #Before invocation.
Added July 6th # 15:21
So, to expedite this current build process and achieve no failing unit tests, I #Ignored this failing unit test and attempted a build. The build failed again but this time the preceding method was the problem child with a similar exception:
java.lang.IllegalStateException: 2 matchers expected, 12 recorded.
This exception usually occurs when matchers are mixed with raw values when recording a method:
foo(5, eq(6)); // wrong
You need to use no matcher at all or a matcher for every single param:
foo(eq(5), eq(6)); // right
foo(5, 6); // also right
I tried a little experiment and #Ignored this current failing method and tried another build but before kinda knew the next preceding method in the class would be the problem child. Lo and behold, it was.
Are you sitting comfortably? Then I will begin...
So I posted this question and of course I kept trying for a solution. I exhausted all channels in fixing the unit tests so I decided to look at this from a different angle. The issue came to light when the development environment was built. I noticed there were two builds quite close together. The former succeeded but the latter failed with the afore mention exception.
Now, going all Columbo I needed to determine the differences between the two builds and it turned out it was one little unit test. This unit test was a straight forward unit test in that it needed no mocking of any sort. What was odd was the Easymock.eq was imported. Strange indeed and even stranger was that it was contained within an assertEquals statement where the 'expected' value was wrapped in this eq(). Yikes and in the wise words of Han Solo, "I've got a bad feeling about this".
I removed this import, together with the eq(), ran the unit test method in isolation...success. I then invoked a build with a test run. Success.
So, what I have learned from this is that using the Easymock.eq() method in the wrong context, in this case an Assert.assertEquals() really strange things happen but still not sure why. Even stranger was that running the unit test in isolation inside my IDE succeeded. :-/
I'll give you a little under the hood of EasyMock insight to help you understand.
When you use a matcher, it is stored in a ThreadLocal. So when the mocked method call actually occurs, a matcher for each parameter is in thread local. EasyMock removes them from there and creates a call expectation.
So, when too many matchers are recording, everything gets misaligned and weird things can happen. That's what the error message is saying. That 12 matchers were recorded but only 2 were expected since you have 2 arguments to your method.
Since Maven and IntelliJ are not forking a new VM between tests, the bad matchers were still there from one test to the other.
Maybe this is counterproductive, I don't know, but right now I am in need of a debugger in IntelliJ that are aware of EasyMock mocks and especially what the mocks methods actually returns.
For example, I have a transport interface ITransport, which has some methods that had to be mocked, and where I only want some of methods returning something. E.g.
ITransport myTransport = createMock(ITransport.class);
I want myTransport.getID() to return a mocked ID 10.
expect(myTransport.getID()).andReturn(10);
With ID 10 I want a method to be invoked once,
expect(myTransport.publish(any(...)));
expectLastCall.once();
Something in the transport class breaks and myTransport isn't called, and my test fails. Know I just want to step through the code with the debugger to check why my test fails. So I add a breakpoint to verify the values of the mocked myTransport object. But they all say "null", even the ID. So I assume, with some brief investigation, that the cause of this is the EasyMock mock class, it doesn't really update the object with value (which sounds reasonable) and instead returns the mocked value at runtime when the method is called.
So, are there any mock aware debuggers for IntelliJ that lets me see which value the method will eventually return.
Yes, and before I receive responses saying that "The debugger is not required if you write unit tests for everything", I just want to state that I know about that. And this is legacy code, or at least code that wasn't written with testing in mind.
This may not be what you're looking for... but it feels like the problem is more on the debugging approach.
A mock object is really just that - a mock - meaning it's a fake empty object that doesn't do anything unless you specifically tell it. When your debugger inspects the mock object, it won't find any values that you did not specifically program it to return. It's not meant to hold values.
EasyMock has an argument capture feature, but since you just want it for debugging, this is probably the wrong approach. Mockito has a spying feature that could be suitable for what you want, but it would involve additional mock-programming statements.
I would say the easiest approach would be to implement your own ITransport just for use in your test class. That way you can implement getID() to always return 10 and put in an assert statement inside your publish(). And you can implement whatever other methods you need in order to capture additional data for debugging purposes. And you get to keep this test-only ITransport for either shared use or future debugging needs.
Indeed, the methods are mocked but the internal implementation of the class is left to itself.
Usually, you don't need to know what is returned since you're the one who recorded it in the first place.
You can also evaluate myTransport.getID() in your debugger. But doing this will consume the expectations.
However, it seems like a good idea to be able to list the all current pending expectations on a mock. And maybe to have a peek function. You can request such features on the EasyMock bug tracker: http://jira.codehaus.org/browse/EASYMOCK
First of all, I have to say, I'm new to mocking. So maybe I'm missing a point.
I'm also just starting to get used to the TDD approach.
So, in my actual project I'm working on a class in the business layer, while the data layer has yet to be deployed. I thought, this would be a good time to get started with mocking. I'm using Rhino Mocks, but I've come to the problem of needing to know the implementation details of a class before writing the class itself.
Rhino Mocks checks if alle the methods expected to be called are actually called. So I often need to know which mocked method is being called by the tested method first, even though they could be called in any order. Because of that I'm often writing complicated methods before I test them, because then I know already in which order the methods are being called.
simple example:
public void CreateAandB(bool arg1, bool arg2) {
if(arg1)
daoA.Create();
else throw new exception;
if(arg2)
daoB.Create();
else throw new exception;
}
if I want to test the error handling of this method, I'd have to know which method is being called first. But I don't want to be bugged about implementation details when writing the test first.
Am I missing something?
You have 2 choices. If the method should result in some change in your class the you can test the results of your method instead. So can you call CreateAandB(true,false) then then call some other method to see if the correct thing was created. In this situation your mock objects will probably be stubs which just provide some data.
If the doaA and doaB are objects which are injected into your class that actually create data in the DB or similar, which you can't verify the results of in the test, then you want to test the interaction with them, in which case you create the mocks and set the expectations, then call the method and verify that the expectations are met. In this situation your mock objects will be mocks and will verify the expected behaviour.
Yes you are testing implementation details, but your are testing the details of if your method is using its dependencies correctly, which is what you want to test, not how it is using them, which are the details you are not really interested in.
EDIT
IDao daoA = MockRepository.GenerateMock<IDao>(); //create mock
daoA.Expect(dao=>dao.Create); //set expectation
...
daoA.VerifyExpectations(); //check that the Create method was called
you can ensure that the expectations happen in a certain order, but not using the AAA syntax I believe (source from 2009, might have changed since,EDIT see here for an option which might work), but it seems someone has developed an approach which might allow this here. I've never used that and can't verify it.
As for needing to know which method was called first so you can verify the exception you have a couple of choices:
Have a different message in your exception and check that to determine which exception was raised.
Expect a call to daoA in addition to expecting the exception. If you don't get the call to daoA then the test fails as the exception must have been the first one.
Often times you just need fake objects, not mocks. Mock objects are meant to test component interaction, and often you can avoid this by querying the state of SUT directly. Most practical uses of mocks are to test interaction with some external system (DB, file system, webservice, etc.), and for other things you should be able to query system state directly.