I discovered that stub and mock are very helpful in testing.
But I wondering about one thing. I think an example will show it clearly.
Class A {
public function isOk() {
// some work
}
public function iAmDepend() {
if ($this->isOk()) {
// do work
}
}
}
class TestA {
public function testIsOk() {
// Test itOk here
}
public function testIAmDepend() {
mock(A)->method(isOk)->return(true);
// tests for iAmDepend
}
}
It wise to do something like this? Stub method of tested class. Or maybe it breaks some rules?
PS. I can't refactore code
Your examples are correct, i.e. testIsOk tests only IsOk, and testIAmDepend only IAmDepend.
But there is important difference between mock and stub that you have to understand: difference between mock and stub.
In your example, if testIAmDepend is verifying that isOk has been called with some arguments and this is part of your assertion for unittest, this is mock. Otherwise this is stub, and you aren't going to verify that it has been called or not.
Related
Suppose, I have a test class with two methods as follows:
public class TestClass {
#Mock
TestClass testObject;
#Test
public void method1() {
doReturn("str").when(testObject).method2();
String s1 = testObject.method2(); // This line gives compilation
//error. Type mismatch cannot convert from void to string
}
#Test
public void method2() {
}
I am basically trying to mock method2 which is a dependency in method1.
But as you can see, the method2 return type is void. So, I am using doReturn to mock it.
As far as my understanding goes, although the method2 's return type is void, after I mock it, the mocked version of method2 should return String type.
But, as I have commented in method1, it is giving type mismatch.
You are simply getting mocking wrong.
Mocking means: instead of create "real" objects of a specific class, you create a stub/dummy/mock that looks like an object of that class. But in reality - it is not.
Beyond that: mocking can not change the signature of a method. So your idea that you could somehow use mocking to have a void method return something is wrong.
You are simply going down the wrong rabbit hole - what you intend to is not possible.
I think you're using the wrong method. doReturn allows you to "inject" the result of the execution. If you want to "falsify" the whole method execution you should consider using doAnswer:
doAnswer(new Answer<Void>() {
public Void answer(InvocationOnMock invocation) {
// whatever you want to execute here...
// Simply return null
return null;
}
}).when(testObject).method2();
I need to test method which looks like this, but my question is: How i should enter this method especially when i can not "mock" AbstractController, and without variable of AbstractController it would not work
public function add(\Queue\Controller\AbstractQueueController $task)
{
//Logic of method
}
You don't need to mock it. You already set it as a parameter, so this test is not about testing AbstractQueueController.
So, for example, if your function looks like this :
public function add(\Queue\Controller\AbstractQueueController $task)
{
$task->doSomething();
}
Then, in the test,AbstractQueueController should receive a call to doSomething method(), and then assert the result of that.
well i did something like that i made extended class
class addtest extends Queue\Controller\AbstractQueueController
{
public function task()
{
}
}
and then in my QueeuServiceTest extended by PHPUnit_framework_TestCase
i made testmethod
public function testadd()
{
$this->queueService->add(new addtest);
}
it covers code but i do not know it is good practice
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
im looking for something similar to what i would do with rhino mocks but in groovy.
i sometimes use partial mocks as well.
in ASP -- Rhino mocks
const string criteria = "somecriteriahere";
ISomeRepository mockSomeRepository = MockRepository.GenerateStrictMock<SomeRepository>();
mockSomeRepository.Expect(m => m.GetSomesByNumber(criteria)).Return(new List<Some>() { });
mockSomeRepository.Expect(m => m.GetSomesByName(criteria)).Return(new List<Some>() { });
mockSomeRepository.Expect(m => m.GetSomesByOtherName(criteria)).Return(new List<Some>() { });
mockSomeRepository.SearchForSomes(criteria);
mockSomeRepository.VerifyAllExpectations();
--------note the virtual -------
public class SomeRepository : ISomeRepository {
public virtual IEnumerable<Some> GetSomesByNumber(string num)
{
//some code here
}
public virtual IEnumerable<Some> GetSomesByName(string name)
{
//some code here
}
public virtual IEnumerable<Some> GetSomesByOtherName(string name)
{
//some code here
}
public IEnumerable<Some> SearchForSomes(string criteria) {
this.GetSomesByNumber(criteria); //tested fully seperatly
this.GetSomesByName(criteria); //tested fully seperatly
this.GetSomesByOtherName(criteria); //tested fully seperatly
//other code to be tested
}
}
GetSomesByNumber, GetSomesByName, GetSomesByOtherName would be tested fully seperatly. If i actually provided values and went into those functions, to me, that seems like in integration test where im testing multiple functionalities and not one unit of work.
So, SearchForSomes i would only be testing that method and mocking away all other dependencies.
In Grails
class XService {
def A() {
}
def B() {
def result = this.A()
//do some other magic with result
}
}
I have tried this -- but failed
def XServiceControl = mockFor(XService)
XServiceControl.demand.A(1..1) { -> return "aaa" }
// Initialise the service and test the target method.
//def service = XServiceControl.createMock();
//def service = XServiceControl.proxyInstance()
// Act
//def result = XServiceControl.B(_params);
XServiceControl.use {
new XService().B(_params)
}
Ive got no idea how to do this, does any one know how?
Thanks
If you're using groovy MockFor (e.g. groovy.mock.interceptor.MockFor), then you need to enclode the usage in a .use{} block.
However, it looks like you are calling mockFor from within a grails.test.GrailsUnitTestCase. In that case, there's no need for the .use{} block: the scope of the mock is the whole test.
thanks for your reply ataylor
seem what i was trying to accomplish is something called partial/half mocking. Here are some links.
http://www.gitshah.com/2010/05/how-to-partially-mock-class-and-its.html
http://mbrainspace.blogspot.com/2010/02/partial-half-mocks-why-theyre-good-real.html
https://issues.apache.org/jira/browse/GROOVY-2630
https://issues.apache.org/jira/browse/GROOVY-1823
http://java.dzone.com/articles/new-groovy-171-constructor
I didnt accomplish this, i ended up extracting B() into its own class and injecting a mock of XService into B's class -- Dependency Injection. I was also informed that extracting away dependencies is a better practice for testing. So, i am now very carefull when using this.() :D
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