How to accept any method call in JMockit? - stub

I have something like the following code:
public void f() {
logger.info("some string");
}
How would I specify in JMockit that any call to logger is allowed? For example, if someone changed the logger call to:
logger.finest("some string");
the test should still pass.

You could create an stubbed-out mock class, as per http://jmockit.googlecode.com/svn/trunk/www/tutorial/StateBasedTesting.html:
#MockClass(realClass = Logger.class, stubs = "", inverse = true)
static class MockLoggerStub { }
Then just call this before running your test:
Mockit.setUpMocks(MockLoggerStub.class);
This will completely stub out the Logger class for your test.

Related

Fixture breaking after service override

This test was run with PHPUnit 3.7.38 by Sebastian Bergmann on Silverstripe 3.4.0
OverrideTest.yml
ExtMember:
ext_member:
Email: ext#email.com
Password: extpassword
OverrideTest.php
class ExtMember extends Member {}
class OverrideTest extends SapphireTest
{
protected static $fixture_file = 'OverrideTest.yml';
public function testBrokenFixtures()
{
$MockExtMember = $this->getMockBuilder('ExtMember')->getMock();
$extMember = $this->objFromFixture("ExtMember", "ext_member");
Injector::inst()->registerService($MockExtMember, 'ExtMember');
$extMemberNull = $this->objFromFixture("ExtMember", "ext_member");
$this->assertEquals("ext#email.com", $extMember->Email);
$this->assertNull($extMemberNull->Email);
}
}
What happened to the $extMemberNull object? Why do all get calls return null after I register the DataObject as a service? This is a massive road block in terms of testability
When you access a property on a DataObject ($extMember->Email) it is handled by magic method __get() and results in calls of either:
$extMember->getEmail();
$extMember->getField('Email');
Since you try to use mock object without configuration, these methods return NULL

Groovy metaclass, mocking a service method that has throws clause

I have an abstract service:
abstract class ParentService {
abstract Map someMethod() throws NumberFormatException
}
And another service that extends above class:
class ChildService extends ParentService {
#Override
Map someMethod() throws NumberFormatException {
//Business Logic
}
}
I want to mock someMethod() using groovy metaClass. I need to mock this method for writing test cases for ChildService. This is what I have done for mocking:
ChildService.metaClass.someMethod = { -> "Mocked method" }
But this is not working and the call always executes actual method from the service. What needs to be done here? Am I missing something?
Please Note that I have to mock just one method not the entire service.
Maybe you could just mock method on instance?
def child = new ChildService()
child.metaClass.someMethod = { -> "Mocked method" }

Mocking methods in grails integration test carries over to other tests

I have an integration test where I sometimes want to mock the return of a service method. However, I have seen that once I mock that method, the subsequent tests that call it will also use the mocked function.
Is this normal? If so, how can I have test which sometimes use mocked functions and sometimes use the real implementation?
Here is my code:
MyController {
def someService
def save(){
...
def val = someService.methodToMock()//sometimes want to mock other times, not
...
}
}
MyTest {
def "test 1"(){
...
//I want to mock here
myController.someService.metaClass.methodToMock = { [] }
...
myController.save()
}
def "test 2"(){
...
//I don't want to mock here, however
// it is returning the mocked results
myController.save()
}
}
In general you don't want to change anything to do with metaclasses in integration or functional tests, only in unit tests. It's expected that you'll be doing this in unit tests and there's automatic support for restoring the original metaclass after each test or after each test class runs depending on the version of Grails and how things are configured. But this isn't the case in integration tests.
There are several different approaches you can use. If you use untyped dependency injection, e.g. def someService, then you can overwrite the real service instance with anything you want, and as long as it has the method(s) that you'll be invoking during the test method the controller won't know or care that it's not the real service.
I like to use a map of closures in this case, since Groovy will invoke a closure as if it were a method. So for 'test 1' you could do this:
def "test 1"() {
...
def mockedService = [methodToMock: { args -> return ... }]
myController.someService = mockedService
...
myController.save()
}
This works because you get a new instance of the controller for each test, and you change the service just for that instance, but the real service isn't affected at all.
Your controller invokes someService.methodToMock(), which is actually someService.get('methodToMock').call(), but the map access and closure invocation syntax can take advantage of Groovy's syntactic sugar to look like a regular method call.
Another option is to subclass the service and override the method(s) that you want, and replace the injected instance with that. This or something like it would be necessary if you type the dependency injection (e.g. SomeService someService). Either create a named subclass (class TestSomeService extends SomeService { ... }) or create an anonymous inner class:
def "test 1"() {
...
def mockedService = new SomeService() {
def methodToMock(args) {
return ...
}
}
myController.someService = mockedService
...
myController.save()
}
Altering the metaClass in one test will absolutely affect other tests. You're altering the groovy system, and need to perform some special cleanup if you're metaClassing. At the end my methods where I metaClass, I call a function to revoke the metaClass changes, passing in the name of the class that was metaClassed, and the instance metaClassed if there was one.
def "some authenticated method test"() {
given:
def user = new UserDomain(blah blah blah)
controller.metaClass.getAuthenticatedUser = { return user }
when:
controller.authenticatedMethod() // which references the authenticated user
then:
// validate the results
cleanup:
revokeMetaClassChanges(theControllerClass, controller)
}
private def revokeMetaClassChanges(def type, def instance = null) {
GroovySystem.metaClassRegistry.removeMetaClass(type)
if (instance != null) {
instance.metaClass = null
}
}
Alternatively, you can just mock the service in the test. A method similar to that mentioned by Burt could be:
def "some test"() {
given:
def mockSomeService = mockFor(SomeService)
mockSomeService.demand.methodToMock(1) { def args ->
return []
}
controller.someService = mockSomeService.createMock()
when:
controller.save()
then:
// implement your validations/assertions
}

Grails 2.0.0 mock service always returns true?

I have a service in my controller I'm trying to mock but it always returns true. The service looks like this:
def someService (x, y){...}
Then I mocked it in my controller test:
mockservice.demand.someService () {-> return false }
It keeps returning true. I don't know what's wrong. I tried including the parameters but its still not returning false. How to do this?
PS: Forgive the typos, I am on my phone right now. Thanks
I'm assuming that you're using this service in an controller, and the unit test is from the controller. I'm assuming also that you read mocking collaborators in the docs.
#TestFor(MyController)
class MyControllerSpec {
def setup() {
def mockServiceControl = mockFor(SomeService)
//here you limit the amount of times that the method should be called.
mockServiceControl.demand.someService(0..1) { x, y ->
return false
}
//probably you're missing to assign the attribute in the controller
controller.someService = mockServiceControl.createMock()
}
void testSomething() {
controller.action()
//assert response
//Then verify that the demand mocking is correct
mockServiceControl.verify()
}
}

Groovy Meta Programming

I want to override a method definition in Grails. I am trying to use Groovy metaprogramming as the class which I want to override belongs to a framework.
Below is the original class.
class SpringSocialSimpleSignInAdapter implements SignInAdapter {
private RequestCache requestCache
SpringSocialSimpleSignInAdapter(RequestCache requestCache) {
this.requestCache = requestCache;
}
String signIn(String localUserId, Connection<?> connection, NativeWebRequest request) {
SignInUtils.signin localUserId
extractOriginalUrl request
}
}
I am trying to override like below
SpringSocialSimpleSignInAdapter.metaClass.signIn = {java.lang.String str, org.springframework.social.connect.Connection conn, org.springframework.web.context.request.NativeWebRequest webreq ->
println 'coming here....' // my implementation here
return 'something'
}
But for some reason overriding is not hapening. I am not able to figure it out. Any help would be greatly appretiated.
Thanks
Yeah, seems like that bug. I don't know your whole scenario, but anyway, here's a small workaround i made:
In your class definition, you don't implement the interface
You create your object and do your metamagic
Use groovy coercion to make it act as the interface and then you can pass it around
Here is a small script i made using JIRA bug to prove it:
interface I {
def doIt()
}
class T /*implements I*/ {
def doIt() { true }
}
def t = new T()
assert t.doIt()
t.metaClass.doIt = { -> false }
// here the coercion happens and the assertion works fine
def i = t as I
assert !i.doIt()
assert !t.doIt()
// here the polymorphism happens fine
def iOnlyAcceptInterface(I i) { assert !i.doIt() }
iOnlyAcceptInterface(i)

Resources