I am trying to write unit test cases for a Kotlin class A and trying to mock return client() call present in test() method to unit test test() method:
A.kt kotlin class:
class A (par 1, par 2) : B(par 1, par 2) {
override fun test(item: String): Boolean {
return client()
}
}
B.kt kotlin class:
abstract class B(par 1, par 2) {
private val client: WebClient by lazy {
//does something
}
protected fun client(): WebClient = client
}
Is it possible to mock the client() call in test() method?
And if possible how to do it and what library should I use for mocking?
This should be doable using Mockito testing framework. However, mocking an object returned from a object's method would require mocking the object itself.
val mockOfA = Mockito.mock(A::class)
val mockOfClient = Mockito.mock(WebClient:class)
Mockito.when(mockOfA.test(anyString())).thenReturn(mockOfClient) // Mind your original snippet return type Boolean from A.test()
If your class A implements internal logic you want to test in your test scenario, there are two possible paths:
Create a Spy instead of a Mock. Mocks do only whatever you explicitly set them up to do. Spy 'falls back' to original implementation when it is not given any mock behaviour.
Rewrite you class A so that it depends on external dependency of a ClientProvider to get an instance of WebClient to return in method test() and inject a mock of said provider to your object of type A during the test.
Related
Imagine I have the following class.
class SomeClass {
public function shortcutMethod($arg1) {
return $this->method($arg1, 'something');
}
public function method($arg1, $arg2) {
// some stuff
}
}
So the shortcutMethod is a shortcut to the other method. Let us say I want to write a test that given and $arg1 the shortcutMethod will correctly call method with the correct arguments.
So far I think I figured I need to mock the class to expect a call to method with some arguments and then call shortcutMethod on the mock object like so (note I am using Mockery).
$mock = m::mock("SomeClass");
$mock = $mock->shouldReceive('method')->times(1)->withArgs([
'foo',
'something'
]);
$mock->shortcutMethod('foo');
This results in an exception like so shortcutMethod() does not exist on this mock object.
Did I misunderstand the usage for mocking? I understand it makes more sense for objects that are dependency injected into the class, but what in this scenario? How would you go about it? And perhabs more importantly, is this sort of testing useless, and if so, why?
You should use mocking to mock out the dependencies of the class under test, not the class under test itself. After all, you are trying to test the real behavior of your class.
Your example is a little basic. How you would test such a class would depend on what your method function does. If it returns a value that is in turn returned by shortCutMethod then I would say that your should just be asserting the output of shortCutMethod. Any dependencies within the method function should be mocked (methods belonging to other classes). I'm not that familiar with mockery, but I've given a tweaked version of your example a go.
class SomeClass {
private $dependency;
public function __construct($mockedObject) {
$this->dependency = $mockedObject;
}
public function shortcutMethod($arg1) {
return $this->method($arg1, 'something');
}
public function method($arg1, $arg2) {
return $this->dependency->mockedMethod($arg1, $arg2);
}
}
$mock = m::mock("mockedClass");
$mock->shouldReceive('mockedMethod')->times(1)->withArgs([
'foo',
'something'
])->andReturn('returnedValue');
$testCase = new SomeClass($mock);
$this->assertEquals(
'returnedValue',
$testCase->shortcutMethod('foo')
);
Having said that, it is possible to partially mock your class under test so that you can test the real behavior of the shortCutMethod function but mock out the method function to assert that it is called with the expected arguments. Have a look at partial mocks.
http://docs.mockery.io/en/latest/reference/partial_mocks.html
I am unit testing my Laravel 4 Controller by mocking my repository that the controller expects. The problem is with the "store" function. This is the function that is called by Laravel when I do a POST to the given controller. The function gets called, but it is expected itemData as an input but I don't know how to provide that. Here is what I've tried:
ItemEntryController
class ItemEntryController extends BaseController
{
protected $itemRepo;
public function __construct(ItemEntryRepositoryInterface $itemRepo)
{
$this->itemRepo = $itemRepo;
}
public function store()
{
if(Input::has('itemData'))
{
$data = Input::get('itemData');
return $this->itemRepo->createAndSave($data);
}
}
}
Test class
<?php
use \Mockery as m;
class ItemEntryRouteAndControllerTest extends TestCase {
protected $testItemToStore = '{"test":12345}';
public function setUp()
{
parent::setUp();
$this->mock = $this->mock('Storage\ItemEntry\ItemEntryRepositoryInterface');
}
public function mock($class)
{
$mock = m::mock($class);
$this->app->instance($class, $mock);
return $mock;
}
public function testItemStore()
{
Input::replace($input = ['itemData' => $this->testItemToStore]);
$this->mock
->shouldReceive('createAndSave')
->once()
->with($input);
$this->call('POST', 'api/v1/tools/itementry/items');
}
Well, you got a few options.
Integration testing
You may want to follow the unit testing docs, which actually has a call() method which allows you set all of this. This bootstraps the app and will use your databases, etc.
This is more of an integration test than unit test, as it uses your actual class implementations.
This may actually be preferable, as Unit testing controllers may not actually make much sense (it doesn't do much, in theory, but call other already-unit-tested classes). But this gets into unit testing vs integration testing vs acceptance testing and all the nuances that apply therein. (Read up!)
Unit Testing
If you're actually looking to unit test, then you need to make your controller unit-testable (ha!). This (likely) means injecting all dependencies:
class ItemEntryController extends BaseController
{
protected $itemRepo;
// Not pictured here is actually making sure an instance of
// Request is passed to this controller (via Service Provider or
// IoC binding)
public function __construct(ItemEntryRepositoryInterface $itemRepo, Request $input)
{
$this->itemRepo = $itemRepo;
$this->request = $input;
}
public function store()
{
if($this->input->has('itemData'))
{
// Get() is actually a static method so we use
// the Request's way of getting the $_GET/$_POST variables
// see note below!
$data = $this->input->input('itemData');
return $this->itemRepo->createAndSave($data);
}
}
}
Sidenote: The Input facade is actually an instance of Request objet with an extra static method get()!
So now that we aren't using Input any longer, and are injecting the Request object, we can unit test this class by mocking the Request object.
Hope that helps!
I'm following the accepted answer in this question but I'm getting a NullReferenceException.
What I need is having a partial mock stub a property (both getter and setter) to behave like a stub (as a simple automatic property). Currently I am able to stub the getter but not the setter.
Is this possible?
EDIT: this is a simple example, I hope it helps explaining my problem.
public class SomeClass
{
public virtual string SomeProperty
{
get{ return SomeMethodDependingOnDBOrAspSession(); }
set{ SomeMethodDependingOnDBOrAspSession(value); } // I want to avoid calling this setter implementation
}
}
var partialMock = MockRepository.GeneratePartialMock<SomeClass>();
partialMock.Stub(p => p.SomeProperty); // I want SomeProperty to behave as an automatic property
When using a PartialMock you can get auto-implemented property like behavior by using PropertyBehavior feature of Rhino Mocks. Given the class in your question, the following nunit test passes for me.
[Test]
public void TestPartialMock()
{
var someClass = MockRepository.GeneratePartialMock<SomeClass>();
someClass.Stub(x => x.SomeProperty).PropertyBehavior();
string val = "yo!";
Assert.DoesNotThrow(() => someClass.SomeProperty = val);
Assert.AreEqual(val, someClass.SomeProperty);
}
If you don't need a PartialMock you could use a Stub which has property behavior by default. You'd simply replace the first two lines of the test with:
var someClass = MockRepository.GenerateStub<SomeClass>();
First-timer here, apologies if I've missed anything.
I'm hoping to get around a call to a static method using Spock. Feedback would be great
With groovy mocks, I thought I'd be able to get past the static call but haven't found it.
For background, I'm in the process of retrofitting tests in legacy java. Refactoring is prohibited. I'm using spock-0.7 with groovy-1.8.
The call to the static method is chained with an instance call in this form:
public class ClassUnderTest{
public void methodUnderTest(Parameter param){
//everything else commented out
Thing someThing = ClassWithStatic.staticMethodThatReturnsAnInstance().instanceMethod(param);
}
}
staticMethod returns an instance of ClassWithStatic
instanceMethod returns the Thing needed in the rest of the method
If I directly exercise the global mock, it returns the mocked instance ok:
def exerciseTheStaticMock(){
given:
def globalMock = GroovyMock(ClassWithStatic,global: true)
def instanceMock = Mock(ClassWithStatic)
when:
println(ClassWithStatic.staticMethodThatReturnsAnInstance().instanceMethod(testParam))
then:
interaction{
1 * ClassWithStatic.staticMethodThatReturnsAnInstance() >> instanceMock
1 * instanceMock.instanceMethod(_) >> returnThing
}
}
But if I run the methodUnderTest from the ClassUnderTest:
def failingAttemptToGetPastStatic(){
given:
def globalMock = GroovyMock(ClassWithStatic,global: true)
def instanceMock = Mock(ClassWithStatic)
ClassUnderTest myClassUnderTest = new ClassUnderTest()
when:
myClassUnderTest.methodUnderTest(testParam)
then:
interaction{
1 * ClassWithStatic.staticMethodThatReturnsAnInstance() >> instanceMock
1 * instanceMock.instanceMethod(_) >> returnThing
}
}
It throws down a real instance of ClassWithStatic that goes on to fail in its instanceMethod.
Spock can only mock static methods implemented in Groovy. For mocking static methods implemented in Java, you'll need to use a tool like GroovyMock , PowerMock or JMockit.
PS: Given that these tools pull of some deep tricks in order to achieve their goals, I'd be interested to hear if and how well they work together with tests implemented in Groovy/Spock (rather than Java/JUnit).
Here is how I solved my similar issue (mocking a static method call which is being called from another static class) with Spock (v1.0) and PowerMock (v1.6.4)
import org.junit.Rule
import org.powermock.core.classloader.annotations.PowerMockIgnore
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.rule.PowerMockRule
import spock.lang.Specification
import static org.powermock.api.mockito.PowerMockito.mockStatic
import static org.powermock.api.mockito.PowerMockito.when
#PrepareForTest([YourStaticClass.class])
#PowerMockIgnore(["javax.xml.*", "ch.qos.logback.*", "org.slf4j.*"])
class YourSpockSpec extends Specification {
#Rule
Powermocked powermocked = new Powermocked();
def "something something something something"() {
mockStatic(YourStaticClass.class)
when: 'something something'
def mocked = Mock(YourClass)
mocked.someMethod(_) >> "return me"
when(YourStaticClass.someStaticMethod(xyz)).thenReturn(mocked)
then: 'expect something'
YourStaticClass.someStaticMethod(xyz).someMethod(abc) == "return me"
}
}
The #PowerMockIgnore annotation is optional, only use it if there is some conflicts with existing libraries
A workaround would be to wrap the static method call into an instance method.
class BeingTested {
public void methodA() {
...
// was:
// OtherClass.staticMethod();
// replaced with:
wrapperMethod();
...
}
// add a wrapper method for testing purpose
void wrapperMethod() {
OtherClass.staticMethod();
}
}
Now you can use a Spy to mock out the static method.
class BeingTestedSpec extends Specification {
#Subject BeingTested object = new BeingTested()
def "test static method"() {
given: "a spy into the object"
def spyObject = Spy(object)
when: "methodA is called"
spyObject.methodA()
then: "the static method wrapper is called"
1 * spyObject.wrapperMethod() >> {}
}
}
You can also stub in canned response for the wrapper method if it's supposed to return a value. This solution uses only Spock built-in functions and works with both Java and Groovy classes without any dependencies on PowerMock or GroovyMock.
The way I've gotten around static methods in Groovy/Spock is by creating proxy classes that are substituted out in the actual code. These proxy classes simply return the static method that you need. You would just pass in the proxy classes to the constructor of the class you're testing.
Thus, when you write your tests, you'd reach out to the proxy class (that will then return the static method) and you should be able to test that way.
I have recently found 'spock.mockfree' package, it helps mocking final classes and static classes/methods.
It is quite simple as with this framework, in this case, you would need only to Spy() the class under test and #MockStatic the static method you need.
Example:
We used a static method returnA of StaticMethodClass class
public class StaticMethodClass {
public static String returnA() {
return "A";
}
}
here is the calling code
public class CallStaticMethodClass {
public String useStatic() {
return StaticMethodClass.returnA();
}
}
Now we need to test the useStatic method of CallStaticMethodClass class But spock itself does not support mock static methods, and we support
class CallStaticMethodClassTest extends Specification {
def 'call static method is mocked method'() {
given:
CallStaticMethodClass callStaticMethodClass = Spy()
println("useStatic")
expect:
callStaticMethodClass.useStatic() == 'M'
}
#MockStatic(StaticMethodClass)
public static String returnA() {
return "M";
}
}
We use the #MockStatic annotation to mark which class needs to be mocked
Directly implement the static method that requires mocking under it, the method signature remains the same, but the implementation is different.
Link to the framework:
https://github.com/sayweee/spock-mockfree/blob/498e09dc95f841c4061fa8224fcaccfc53904c67/README.md
Here is my situation:
I want to test on the "HasSomething()" function, which is in the following class:
public class Something
{
private object _thing;
public virtual bool HasSomething()
{
if (HasSomething(_thing))
return true;
return false;
}
public virtual bool HasSomething(object thing)
{
....some algo here to check on the object...
return true;
}
}
So, i write my test to be like this:
public void HasSomethingTest1()
{
MockRepository mocks = new MockRepository();
Something target = mocks.DynamicMock(typeof(Something)) as Something;
Expect.Call(target.HasSomething(new Object())).IgnoreArguments().Return(true);
bool expected = true;
bool actual;
actual = target.HasSomething();
Assert.AreEqual(expected, actual);
}
Is my test written correctly?
Please help me as i can't even get the result as expected. the "HasSomething(object)" just can't be mock in that way. it did not return me 'true' as being set in expectation.
Thanks.
In response to OP's 'answer': Your main problem is that RhinoMocks does not mock members of classes - instead it creates mock classes and we can then set expectations and canned responses for its members (i.e. Properties and Functions). If you attempt to test a member function of a mock/stub class, you run the risk of testing the mocking framework rather than your implementation.
For the particular scenario of the logical path being dependent on the return value of a local (usually private) function, you really need an external dependency (another object) which would affect the return value that you require from that local function. For your code snippet above, I would write the test as follows:
[Test]
public void TestHasSomething()
{
// here I am assuming that _thing is being injected in via the constructor
// you could also do it via a property setter or a function
var sut = new Something(new object());
Assert.IsTrue(sut.HasSomething);
}
i.e. no mocking required.
This is one point of misunderstanding that I often had in the past with regards to mocking; we mock the behaviour of a dependency of the system under test (SUT). Something like: the SUT calls several methods of the dependency and the mocking process provides canned responses (rather than going to the database, etc) to guide the way the logic flows.
A simple example would be as follows (note that I have used RhinoMocks AAA syntax for this test. As an aside, I notice that the syntax that you are using in your code sample is using the Record-Replay paradigm, except that it isn't using Record and Replay! That would probably cause problems as well):
public class SUT
{
Dependency _depend
public SUT (Dependency depend)
{
_depend = depend;
}
...
public int MethodUnderTest()
{
if (_depend.IsReady)
return 1;
else
return -1;
}
}
...
[Test]
public void TestSUT_MethodUnderTest()
{
var dependency = MockRepository.GenerateMock<Dependency>();
dependency.Stub(d => d.IsReady).Return(true);
var sut = new SUT(dependency);
Assert.AreEqual(1, sut.MethodUnderTest());
}
And so the problem that you have is that you are attempting to test the behaviour of a mocked object. Which means that you aren't actually testing your class at all!
In a case like this, your test double should be a derived version of class Something. Then you override the method HasSomething(object) and ensure that HasSomething() calls your one.
If I understand correctly, you are actually interested in testing the method HasDynamicFlow (not depicted in your example above) without concerning yourself with the algorithm for HasSomething.
Preet is right in that you could simply subclass Something and override the behavior of HasSomething to short-circuit the algorithm, but that would require creating some additional test-dummy code which Rhino is efficient at eliminating.
Consider using a Partial Mock Stub instead of a Dynamic Mock. A stub is less strict and is ideal for working with Properties. Methods however require some extra effort.
[Test]
public void CanStubMethod()
{
Foo foo = MockRepository.GenerateStub<Foo>();
foo.Expect(f => f.HasDynamicFlow()).CallOriginalMethod(OriginalCallOptions.NoExpectation);
foo.Expect(f => f.HasSomething()).CallOriginalMethod(OriginalCallOptions.NoExpectation);
foo.Expect(f => f.HasSomething(null)).IgnoreArguments().Return(true);
Assert.IsTrue(foo.HasDynamicFlow());
}
EDIT: added code example and switched Partial Mock to Stub