JMockit basics: mocked object, mocked parameter, expectation - jmockit

I just started using JMockit and I am a bit confused on some basics of JMockit, in terms of when mock object is created, mocked object scope and what is the effect of mock etc. Please help with the following questions.
My questions refer to the following code:
public class MyClassTest
{
#Mocked({"method1","method2"})
ClassA classA; //ClassA has only static method
#Mocked
ClassB classB;
#Test
public void test1()
{
new NonStrictExpectations() {{
MyClassA.method3(classB);
result = xxx;
}};
// testing code
....
// verification
...
}
#Test
public void test2(#Mocked ClassC classC)
{
...
}
}
Questions:
About #Mocked declared as a instance variable for a junit test, like #Mocked ClassB classB:
(1) For junit, the instance variable is newly created for each test (like test1(), test2()), right? Is it true that before each test runs, a new mocked instance of ClassB is created?
(2) It mocks the class. It makes all methods in ClassB mocked for all tests (test1() and test2() in this case), right?
(3) If methods are specified for mocked object, like "#Mocked({"method1","method2"}) ClassA classA;", it means only method1 and method2 can be mocked? Can other methods be added to be mocked in Expectations for a test?
About #Mocked parameter passed in to test, like "#Mocked ClassC classC" for test2:
I assume this mock should not affect other tests? Is it true that ClassC is only mocked in test2()?
Expectation:
(1) For expectation specified in a test, is its scope local to the test, meaning the mocked method is only effective in this test? For example, ClassA.method3() is only mocked in test1(), right?
(2) The recorded method in expectation only runs when the matching method is invoked from the testing code, is it? If recorded method parameter does not match, will it run the real method?
I am getting an exception in ClassA.method3() when running test1(). Somehow the real method of ClassA.method3() is executed and gave exception. I guess it is due to parameter mismatch for ClassA.method3()?

Answering your questions:
(1) Yes; (2) yes; (3) yes, and other methods cannot be mocked in this same test class.
Yes, only in the test which has the mock parameter.
(1) Right, the expectation is only valid within the scope where it's recorded. (2) No, once mocked, the real implementation of a method is never executed.
As for the exception you get, I can't tell why it happens without seeing a complete test.

Related

mockk, clearAllMocks or unmockkAll

mockk 1.9.3
In the test noticed if did static mock in previous test, the next test will be using same mock.
Thought to do a reset at #After, but not sure which one to use clearAllMocks or unmockkAll.
in https://mockk.io/
unmockkAll unmocks object, static and constructor mocks
clearAllMocks clears regular, object, static and constructor mocks
but not clear what are the difference by unmocks and clears.
e.g.
#Test
fun test_1() {
mockkStatic(TextUtils::class)
every { TextUtils.isEmpty(param } returns true
//test
doSomeThingUsingTextUtils()
// verify
... ...
}
#Test
fun test_2() {
// in this test it does not want the mocked stub behavior
}
What it should use, clear or 'unmock`?
For me, understanding the difference between Clearing and Unmocking was sufficient.
clear - deletes internal state of objects associated with mock
resulting in empty object
unmock - re-assigns transformation of
classes back to original state prior to mock
(Source)
PS: I understand the confusion! I had it as well!
Let me know if you have any questions. Thanks.

Specifying method's behaviour via EXPECT_CALL vs in body

From what I understand gmock (and I'm new to it) EXPECT_CALL allows for specifying how a method will behave when it's called (in this case I'm mostly interested in what it will return). But I could just as well define the method explicitly with its body. Example:
class Factory
{
int createSomething();
};
class MockFactory : public Factory
{
MOCK_METHOD0(createSomething, int());
};
int main()
{
...
int something(5);
MockFactory mockFactory;
EXPECT_CALL(mockFactory, createSomething()).WillRepeatedly(Return(something));
...
}
vs
class MockFactory : public Factory
{
int createSomething()
{
return 5;
}
};
Now, if createSomething were to behave differently (return different things) in different scenarios then obviously I should use EXPECT_CALL. But if it's going to always return the same thing wouldn't it be better to just explicitly define the method's body? (Note that other methods in the mocked class might still use EXPECT_CALL.)
When you define a method you miss all the flexibility that mocking that method can give you in the tests.
If you need to assert in a test that createSomething gets called, you can only do it if you have mocked it, not if you have a standard method definition. Not in this case, but in case of methods taking parameters, it's even better to have a mock.
If you need to set up a default action that your method should perform, even when you don't set any expectations on it, do so using ON_CALL macro in the SetUp member function of a TestFixture.

Mocking a private method in an Expectations block causes "IllegalStateException: Missing invocation to mocked type at this point"

I have a JUnit test that uses a JMockit Expectations block:
#Tested
private MyTestedClass myTestedClass;
#Injectable
private MyOtherClass myOtherClass;
#Test
public void publicBooleanMethodTest() {
new Expectations() {{
invoke(myOtherClass, "privateMethod");
result = true;
}};
myTestedClass.run(); // Calls myOtherClass.privateMethod();
}
However, this results in the following error:
java.lang.IllegalStateException: Missing invocation to mocked type at this point; please make sure such invocations appear only after the declaration of a suitable mock field or parameter
As you can see, myClass is mocked via #Injectable, so I'm not sure why the error is happening. I have also found that if I change the scope of privateMethod() to public, everything works.
What is going on and how can I fix this? It worked fine in JMockit 1.22, but now fails in JMockit 1.23 and greater.
JMockit 1.23 removed support for mocking private methods in Expectations blocks. From the release notes:
Version 1.23 (Apr 24, 2016):
Dropped support for the mocking of private methods/constructors when using the Expectations API, to prevent misuse. If still needed, they can be mocked or stubbed out with the application of a MockUp<T>.
Unfortunately, the erroneous error message is currently seen as "too costly too fix" by the development team. A better error message was added in JMockit 1.28 as a result of this discussion.
The error log says to use MockUp<T> as an alternative. In this case, the code would be as follows:
#Tested
private MyTestedClass myTestedClass;
#Injectable
private MyOtherClass myOtherClass;
#Test
public void publicBooleanMethodTest() {
// Partially mock myOtherClass
new MockUp<MyOtherClass>(myOtherClass) {
#Mock boolean privateBooleanMethod() {
return true;
}
};
myTestedClass.run(); // Calls myOtherClass.privateMethod();
}

Mocking Objective-C code in Swift Unit-Tests

NOTE: This isn't my actual code, I re-typed it in a simple fashion on to here for your help.
I have this class written in Objective-C
#interface MySpecialManager <NSObject>
+ (MySpecialManager *)sharedInstance;
-(void)someFunctionWithParamOne:(NSString *)paramOne andParamTwo:(NSString *)paramTwo;
-(void)someFunctionWithParamOne:(NSString *)paramOne andParamTwo:(NSString *)paramTwo success:(void (^)(NSString *))success failure:(void (^)(NSError *error))failure;
#end
I have unit tests (in Swift) for the second function with the success/failure blocks but I am now trying to write unit tests for the first function. All this function does is call the second function. Therefore, I was thinking the best way to test this would be to just check that the second function does indeed get called and with the correct parameters. Therefore, I thought mocking/stubbing was the way to go forward but I am struggling to understand how exactly to unit test this.
From much Googling I read that creating my own Mock object would be the way to go forward so I have this now (written in Swift):
class MockMySpecialManager: NSObject, MySpecialManagerProtocol {
var functionOneWasCalled = false
var functionTwoWasCalled = false
func someFunctionWithParamOne(paramOne: String!, andParamTwo paramTwo: String!) {
functionOneWasCalled = true
}
func someFunctionWithParamOne(paramOne: String!, andParamTwo paramTwo: String!, success: ((String!) -> Void)!, failure: ((NSError!) -> Void)!) {
functionTwoWasCalled = true
}
If in my test though I initialise a MockMySpecialManager and call the first method, it won't call the second one as it just updates the boolean, correct? I could update the mock function to call the second but that feels like cheating and not a real unit test as its not testing my code. How can I test this?
I somehow (or so I think) need to set the manager to MySpecialManager.sharedInstace(), call the first method and then check if my second method was called on the mock.
Any help? What am I misunderstanding/where am I going wrong?
Your current MOC class is actually a complete replacement of the target class, so you aren't actually testing it at all.
If your MOC was a subclass of the target class instead, and only implemented the second method, then the test can call the first method and the MOC can verify that the second method was called.
Often you would use a mocking library to assist with this, and those libraries allow you different ways to do the same thing as above.
Alternatively you wouldn't MOC the target class, you would MOC all of its dependencies. Then your test checks that the dependencies are called appropriately and with the requisite parameters. Then your first and second method tests are the same setup but with slightly different expectations.

Too few interactions in a Spock test for a Grails service

I thought I've understood Spock interactions but I have to admin that I'm still missing some pieces of the picture.
Alright, here my problem: I have a method in a Grails service which performs some operations, including a call to a void method of the same service class. Here's the code:
class myService {
void myStuff(def myObj, params) {
// do my stuff
anotherMethod(myObj)
//do my stuff again
}
void anotherMethod(myObj) {
// do other stuff
}
}
I want to be sure that myStuff method calls anotherMethod, to test and document the correct behaviour.
So, here's the test in my Spock Specification class:
void 'test myStuff method'() {
given: 'my object and some params'
// doesn't really matter what I'm doing here
MyObject myObj = new MyObject()
params = [title: 'my object']
when: 'we call myStuff()'
service.myStuff(myObj, params)
then: 'anotherMethod() is called exactly one times'
1 * service.anotherMethod(myObj)
}
}
The error I get is:
Too few invocations for:
1 * service.anotherMethod(myObj) (0 invocations)
What do you think? What's wrong?
As always, thanks in advance.
You are asking for a very special, and generally discouraged, form of mock called partial mocking where methods on the class under test are mocked. Spock supports this since 0.7, but you'll have to create a Spy() rather than a Mock(). Also note that you cannot mock private methods. For more information on spies, see the reference documentation.