Groovy MockFor demands not acting as expected for stream - unit-testing

I wanted to create a unit test verifying that a stream was closed. My class decorates the stream it receives with DataputStream, which seems to break the mocking demands feature.
void testBadMock() {
def mockInputClass = new MockFor(InputStream)
mockInputClass.demand.with {
close() {}
}
def mockInput1 = mockInputClass.proxyInstance()
mockInput1.close()
mockInputClass.verify mockInput1 // passes
def mockInput2 = mockInputClass.proxyInstance()
new DataInputStream(mockInput2).close()
mockInputClass.verify mockInput2 // fails
}
The specific error message:
junit.framework.AssertionFailedError: verify[0]: expected 1..1 call(s) to 'close' but was called 0 time(s).
I checked the source code for DataInputStream, and as expected, the stream passed into the constructor is the object which it delegates the close() method call to.
def fakeInput = [close: {println 'I was called'}] as InputStream
new DataInputStream(fakeInput).close() // prints 'I was called'
I see no reason why my mock object is not seeing the close() method call.

A potential workaround:
def mockInput2 = mockInputClass.proxyInstance()
new DataInputStream([close: { mockInput2.close() }] as InputStream).close()
mockInputClass.verify mockInput2

Related

How to throw an exception upon first invocation and a regular return value on the second?

My code makes network calls. Sometimes these fail and I've implemented some retry logic. Now I wish to test this with a unit test. I'm using Mockito for this. I'm having trouble mocking this particular method call, this is my test code:
var mock = MockHttpClient();
var answers = <Future<String>>[
Future.error(Exception('boom')),
Future.value('some return value'),
];
when(mock.getStuff()).thenAnswer((_) => answers.removeAt(0));
var client = Client(inner: mock);
var result = client.someCall(); // This method call uses the `inner` object to make the `getStuff` network call.
expect(result, 'some return value');
Running this code throws an exception. And I get that because of the first returned Future! Mockito has the appropriate method call named thenThrow but I can't figure out how to combine the two.
I've figured it out. The trick is not to use a Mock but a Fake.
That looks like this:
class FakeHttpClient extends Fake implements HttpClient {
final List<Future<List<String>>> answers = [
Future.error(Exception('boom')),
Future.value('some return value'),
];
#override
Future<String> getStuff() {
return answers.removeAt(0);
}
}
Then use an instance of FakeHttpClient as an argument to the original example's Client:
var fake = FakeHttpClient();
var client = Client(inner: fake);
var result = client.someCall(); // This method call uses the `inner` object to make the `getStuff` network call.
expect(result, 'some return value');

Meaning of closure in then clause in spock

We are in process of writing Unit test cases using Spock, I am not able to understand the following code snippet in then section varifying the declaration,
then:
1 * service.fraudMigrationOnboardingService.onboard(_) >>
{merchantId -> successCallBack.call(response)}
what is the meaning of the above code.
Because your question is lacking detail, I have to speculate and make an educated guess about your test. :-/
So you have a service with a member or getter fraudMigrationOnboardingService.
fraudMigrationOnboardingService has a method onboard taking a single parameter.
Obviously fraudMigrationOnboardingService is a mock or spy, which is why you can check interactions like 1 * ... on it.
The developer who wrote this test and whom, as it seems, you are too shy to ask about its meaning or who has left your company, wanted something specific to happen when method onboard(_) is called (probably by service) during the test: a call-back method call. Thus she declared the method stub { merchantId -> successCallBack.call(response) } as a replacement for what onboard(_) would normally do in this case. In a spy it would execute the original method, in a mock it would no nothing at all. But obviously that is not the desired behaviour, maybe because the test relies on different behavious later on.
In general, I think a test which is hard to read should be refactored, but anyway, here I am replicating your situation:
package de.scrum_master.stackoverflow
import spock.lang.Specification
class DummyTest extends Specification {
static class Service {
FraudMigrationOnboardingService fraudMigrationOnboardingService
void doSomething(String name) {
println "Doing something"
fraudMigrationOnboardingService.onboard(name)
}
}
static class FraudMigrationOnboardingService {
void onboard(String name) {
println "On-boarding $name"
}
}
static class SuccessCallBack {
void call(int httpResponse) {
println "Callback HTTP response = $httpResponse"
}
}
def "Some service test"() {
given:
def onboardingService = Mock(FraudMigrationOnboardingService)
def service = new Service(fraudMigrationOnboardingService: onboardingService)
def successCallBack = new SuccessCallBack()
def response = 200
when:
service.doSomething("ACME Inc.")
then:
1 * service.fraudMigrationOnboardingService.onboard(_) >>
{ merchantId -> successCallBack.call(response) }
}
}
The console log says:
Doing something
Callback HTTP response = 200
If you would comment out >> { merchantId -> successCallBack.call(response) }, it would only print
Doing something
for a mock and if you also change the Mock(FraudMigrationOnboardingService) into a Spy(FraudMigrationOnboardingService) it would print
Doing something
On-boarding ACME Inc.
Update: Maybe you still don't understand what the closure means, I am not sure. So I will explain it a bit more: As I said, it is just a stub for the onboard(String) method. The method parameter is mapped to merchantId but not used in the stubbed method. Instead the callback is triggered.

Understanding Grails mockFor demand

I'm trying to write a unit test for my filters, and I'm struggling to understand the demand for my mocked object. Here is a simple failing test:
void "test my sanity"() {
setup:
def vendorPayment = mockFor(Payment)
vendorPayment.demand.buyerId { -> 123}
def vp = vendorPayment.createMock()
//vp.buyerId=123
println "buyer id: ${vp.buyerId}"
when:
def a = "testing"
then:
vp.buyerId == 123
}
I wanted to mock the getter for buyerId. Using demand doesn't work, but if I create the mock and then set the buyer id (the commented line), the test will pass. Does demand not work with getters? Is it because the getter is implicitly/dynamically created?
Method getBuyerId has to be mocked. Groovy adds the accessor methods for you in compile time, so method on demand has to be mocked. Take this simple case:
class Payment {
Integer buyerId
}
Getter/Setter for Payment.groovy will be added when the class is converted to bytecode after compile. Corresponding test would look like:
void "test my power"() {
setup:
def vendorPayment = mockFor(Payment)
vendorPayment.demand.getBuyerId(1..2) { -> 123}
def vp = vendorPayment.createMock()
println "buyer id: ${vp.buyerId}"
expect:
vp.buyerId == 123
//This would fail for < 2.3.* because of this bug which is fixed in 2.4
//http://jira.grails.org/browse/GRAILS-11075
vendorPayment.verify() //null
}
Note the changes that was made:
getBuyerId method is mocked instead of the field buyerId
test demands that getBuyerId will be called 1 to 2 times (first while printing, second in then block). By default if nothing is specified, it assumes the method will be called once, which would fail in this case as getBuyerId is invoked twice.
We can also verify that the mock control did its job after the test is done

PHPUnit Mock overrides existing methods

I'm writing a unit test for a REST Service connector which is using a third party tool called Httpful.
Because I do not want to send real requests to the server, I mocked the "send" method from Httpful\Request:
$mockedRequest = $this->getMock('Httpful\Request', array('send'), array(), '', false);
$mockedRequest->expects($this->once())->method('send');
This works fine, but the Request Class has a method called expects itself, which I use in my actual code to define the acceptable mime type of the response.
$this
->getRequest('GET')
->uri(ENDPOINT . $configurationId) //by default this returns a Request Object (now mocked request)
->expects('application/json') //crashes ...
->send();
When the code gets executed, I get the following error (which is understandable):
Argument 1 passed to Mock_Request_938fb981::expects() must implement interface PHPUnit_Framework_MockObject_Matcher_Invocation, string given
Is there something like a configurable prefix for methods coming from the Mock Class like "expects"?
I don't think that you will be able to do that using the PHPUnit_MockObject class. But you can code your own and use that instead.
class MockRequest extends \Httpful\Request {
public $isSendCalled = false;
public $isUriCalled = false;
public $isExpectsCalled = false;
public function uri($url) {
if($url !== '<expected uri>') {
throw new PHPUnit_Framework_AssertionFailedError($url . " is not correct");
}
$this->isUriCalled = true;
return $this;
}
public function expects($type) {
if($type !== 'application/json') {
throw new PHPUnit_Framework_AssertionFailedError($type . " is not correct");
}
$this->isExpectsCalled = true;
return $this;
}
public function send() {
$this->isSendCalled = true;
}
}
Your line for creating the mock then just becomes:
$mockedRequest = new MockRequest();
If the constructor fo
Then in your test you can verify that the methods are called with
$this->assertTrue($mockedRequest->isSendCalled);
$this->assertTrue($mockedRequest->isUriCalled);
$this->assertTrue($mockedRequest->isExpectsCalled);
This isn't a very dynamic mock but it will pass the type hinting and does your check for you. I would create this mock in the same file as your test (though be careful about not accidentally redefining this class elsewhere in your test suite). But it gets you around the problem of having expects being overridden.
The PHPUnit_Framework_MockObject_MockObject is an interface that sets the signature for expects() also which your class wouldn't meet and so there would be an error if you were able to rename the method.
https://github.com/sebastianbergmann/phpunit-mock-objects/blob/master/src/Framework/MockObject/MockObject.php

No such property in Groovy test case

I have a Groovy test class MsgDispatcherTest extends GroovyTestCase.
Within this class there is the following test case:
#Test
void test_register()
{
def d = MsgDispatcher.instance // MsgDispatcher is a singelton
def cb1Called = 0
def cb1 = { cb1Called++; void }
d.registerCallback("msg1", cb1) // closure cb1 should be registered
}
And the interface of MsgDispatcher.registerCallback looks like this:
void registerCallback(String message, Closure callback)
{
assert callback && message
// ...
}
Now when I run this test case I get the following error message on the call to d.registerCallback("msg1", cb1):
groovy.lang.MissingPropertyException: No such property: msg1 for class: ecs.MsgDispatcherTest
Any ideas what I am missing here?
Ok, I found the problem. There was a bug in my registerCallback() method. The issue was that I have tried to access the callback parameter as map (callback[message]), which of course does not work.
That's ok, I understand why this is a problem. However, why is the Groovy compiler error message so cryptic? It was referring not to that problematic line within registerCallback(), but instead to the line where I call that function.