given a domain constellation like this:
abstract class A {
def myService
def beforeInsert() {
myService.doIt()
}
}
class B extends A {
def beforeInsert() {
super.beforeInsert()
}
}
Is it possible to mock the following methods:
- beforeInsert() in B?
- beforeInsert() in A?
For making service method calls optional for unit testing the easiest thing to do is to use null safe method calls:
abstract class A {
def myService
static transients = ['myService']
def beforeInsert() {
myService?.doIt()
}
}
class B extends A {
def beforeInsert() {
super.beforeInsert()
}
}
Save B objects without flushing in unit tests or
override beforeInsert by metaClass:
B.metaClass.beforeInsert = {-> }
Related
I have the following classes shown below, legacy code. The goal I want to achieve is to ensure that the delegate method processUser is called with the user data passed. Second, I also want to ensure that the passed in Registration object's doRegister is called. My attemot is shown below for the delegate, but the test does not pass as it says, Too few invocations. I am using Groovy spock for testing version 1.2
class Invoker {
Delegate delegate;
Invoker(Delegate delegate) {
this.delegate = delegate;
}
void invoke(UserData user) {
delegate.processUser(user);
}
}
class Delegate {
private RegistrationService service;
Delegate (RegistrationService r) {
this.service = r;
}
void processUser(UserData data) {
service.doRegistration(data);
}
}
class DelegateSpec extends Specification {
Delegate delegate
RegistrationService registration
Invoker invoker
def setup() {
registration = Mock()
delegate = new Delegate(registration)
Invoker invoker = new Invoker(delegate)
}
def "Invoker should invoke delegate passed to it"() {
given:
UserData u = ....
when:
invoker.invoke(u)
then:
1* delegate.processUser(u)
}
}
First let me provide a fully consistent set of classes in order to be able to compile the application code:
package de.scrum_master.stackoverflow.q59366025;
public class UserData {}
package de.scrum_master.stackoverflow.q59366025;
public class RegistrationService {
public void doRegistration(UserData data) {}
}
package de.scrum_master.stackoverflow.q59366025;
class Delegate {
private RegistrationService service;
Delegate (RegistrationService r) {
this.service = r;
}
void processUser(UserData data) {
service.doRegistration(data);
}
}
package de.scrum_master.stackoverflow.q59366025;
class Invoker {
Delegate delegate;
Invoker(Delegate delegate) {
this.delegate = delegate;
}
void invoke(UserData user) {
delegate.processUser(user);
}
}
Now as for your test, you are making it more complicated than necessary and there is also a logical error:
If the Delegate is not mock or spy, you cannot check interactions like 1 * on it.
So just make it a mock, then you also do not need to inject its RegistrationService dependency anymore - which is the whole point of creating a mock.
package de.scrum_master.stackoverflow.q59366025
import spock.lang.Specification
class DelegateSpec extends Specification {
def delegate = Mock(Delegate)
def invoker = new Invoker(delegate)
def "Invoker should invoke delegate passed to it"() {
given:
def userData = new UserData()
when:
invoker.invoke(userData)
then:
1 * delegate.processUser(userData)
}
}
I have a controller class with a method something() which makes calls to two different methods of the same class and merge the result of two calls.
class Controller{
...
public UDC doSomething(){
CompletableFuture<UDC> feature1 = CompletableFuture.supplyAsync(()-> {this.doOther()}).exceptionally(ex -> {return new SomeException();});
CompletableFuture<UDC> feature2 = CompletableFuture.supplyAsync(()-> {this.doSomeOther()}).exceptionally(ex -> {return new SomeException();});
...
return feature1.combine(feature2).get();
}
...
}
I don't think you should use Mockito to mock CompletableFuture here, any of them...
In the test, treat the Controller's doSomething functionality as a black box that given some input returns UDC.
Now, it's possible that doOther and/or doSomeOther call some external code that should be mocked. In this case the Controller looks probably something like this:
class Controller {
private final SomeExternalDependency dependency1;
public Controller(SomeExternalDependency dependency1) {
this.dependency1 = dependency1;
}
private UDC doOther() {
...
dependency1.foo();
...
}
private UDC toSomeOther() {
...
dependency1.bar();
...
}
}
In this case in the test you can mock out the dependency1 with mockito as usual:
class MyTest {
#Test
public void doSomething() {
SomeExternalDependency dep = Mockito.mock(SomeExternalDependency.class);
// specify the expectations
Controller controller = new Controller(dep);
controller.doSomething();
}
}
Is it possible to mock the
EntityRepository::findOneBy{$field}($value)
function?
Using:
->getMock('EntityRepository')
->expects($this->any())
->method('findOneByField')
resolves always in null, as findOneByField isn't a real function but gets mapped by __call(). At least I think that that is the problem..
You can mock the __call method. Will give a simple example:
Class:
class A {
public function __call($fname, $args) {
if($fname === 'test') {
return 'test';
}
}
}
Test:
class ATest extends PHPUnit_Framework_TestCase
{
public function testA() {:
$mock = $this->getMock('A');
$mock->expects($this->any())
->method('__call')
->with('test')
->will($this->returnValue('test'));
var_dump($mock->test());
}
}
You can do the same with the EntityRepository. I just hadn't one by the hand for testing.
I'm running into an issue when unit testing a controller. In attempting to test a request, the test incorrectly directs to the wrong method. Example below, which should clearly illustrate the problem.
Parent Controller
class ExampleParentController {
def someMethod = {
render "FALSE"
}
def someMethod(def object)
{
render "DEFINITELY FALSE"
}
}
Child Controller
class ExampleChildController extends ExampleParentController {
def someMethod = {
render "TRUE"
}
}
Test Class
class ExampleChildControllerTests extends ControllerUnitTestCase {
protected void setUp() {
super.setUp()
}
protected void tearDown() {
super.tearDown()
}
void testSomeMethod() {
controller.someMethod()
def result = controller.response.contentAsString
assertEquals ("TRUE", result)
}
}
I would expect that controller.someMethod() would render "TRUE". This works perfectly when executed while the application is running, as someMethod(def object) isn't exposed as an endpoint. Is there a way to specify which method to execute?
I'm trying to mock a service in an integration test for a dynamically scaffolded controller. I get an error indicating that the controller property for the service is not accessible from the test.
It seems that dynamically scaffolded controllers can't be tested with unit tests at all so I'm using integration tests. I want to mock the service to test error handling in my app. Is this a bug in Grails 2.2.0 or am I just doing it wrong?
The result for grails test-app is:
groovy.lang.MissingPropertyException: No such property: myService for class: MyController
Example:
I have modified the src/templates/scaffolding/Controller.groovy:
class ${className}Controller {
MyService myService
def action() {
render myService.serviceMethod()
}
}
Dynamically scaffolded MyController.groovy:
class MyController {
static scaffold = MyDomainClass
}
Integration test MyControllerTests.groovy:
class MyControllerTests extends GroovyTestCase {
def myController
#Before
void setUp() {
myController = new MyController()
}
void testMock() {
myController.myService = [ serviceMethod : { return "foo" } ] as MyService
controller.action()
}
}
Try using the setter method:
void testMock() {
myController.setMyService([ serviceMethod : { return "foo" } ])
controller.action()
}
If you execute: println c.metaClass.methods*.name, you will see that there are methods like getSetMyService() and getGetMyService(). I'm not sure of it, but probably Grails is not adding fields but instead getters for field get/set methods.
The integration test should be implemented as shown below. If we mock the service in a test we must reset it ourselves. Grails does not do it for us which is mysterious because the controller is created in setUp().
droggo's answer above reveals the correct way to inject the mock in the SUT. I'll also add an example of using a Groovy mock. It's bit more verbose though.
class MyControllerTests extends GroovyTestCase {
def myController
def myService
#Before
void setUp() {
myController = new MyController()
}
#After
void tearDown() {
myController.setMyService(myService)
}
void testMapMock() {
myController.setMyService([ serviceMethod : { return "foo" } ] as MyService)
controller.action()
}
void testGroovyMock() {
def myServiceMockContext = new StubFor(MyService)
myServiceMockContext.demand.serviceMethod() { -> return "bar" }
def myService = myServiceMockContext.proxyInstance()
controller.setMyService(myService)
controller.action()
}
}