Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock the 'new' operator

I'm testing some groovy code that uses a java library and I want to mock out the library calls because they use the network. So the code under test looks something like:

def verifyInformation(String information) {
    def request = new OusideLibraryRequest().compose(information)
    new OutsideLibraryClient().verify(request)
}

I tried using MockFor and StubFor but I get errors such as:

No signature of method: com.myproject.OutsideLibraryTests.MockFor() is applicable for argument types: (java.lang.Class) values: [class com.otherCompany.OusideLibraryRequest]  

I'm using Grails 2.0.3.

like image 664
user1394451 Avatar asked May 14 '12 18:05

user1394451


People also ask

Can we mock constructor using Mockito?

Starting with Mockito version 3.5. 0, we can now mock Java constructors with Mockito. This allows us to return a mock from every object construction for testing purposes.

How do you mock an object in JUnit?

We can use Mockito class mock() method to create a mock object of a given class or interface. This is the simplest way to mock an object. We are using JUnit 5 to write test cases in conjunction with Mockito to mock objects.


2 Answers

I've just found that we can always overwrite a constructor via MetaClass, as Grails 2 will be reset MetaClass modification at the end of each test.

This trick is better than Groovy's MockFor. AFAIK, Groovy's MockFor does not allow us to mock JDK's classes, java.io.File, for example. However in the below example, you cannot use File file = new File("aaa") as the real object type is a Map, not a File. The example is a Spock specification.

def "test mock"() {
    setup:
    def fileControl = mockFor(File)
    File.metaClass.constructor = { String name -> [name: name] }
    def file = new File("aaaa")

    expect:
    file.name == "aaaa"
}
like image 149
chanwit Avatar answered Oct 31 '22 12:10

chanwit


The second, optional parameter to MockFor's constructor is interceptConstruction. If you set this to true, you can mock the constructor. Example:

import groovy.mock.interceptor.MockFor
class SomeClass {
    def prop
    SomeClass() {
        prop = "real"
    }
}

def mock = new MockFor(SomeClass, true)
mock.demand.with {
    SomeClass() { new Expando([prop: "fake"]) }
}
mock.use {
    def mockedSomeClass = new SomeClass()
    assert mockedSomeClass.prop == "fake"
}

Note, however, you can only mock out groovy objects like this. If you're stuck with a Java library, you can pull the construction of the Java object into a factory method and mock that.

like image 28
ataylor Avatar answered Oct 31 '22 13:10

ataylor