0

I am trying to mock an instance method within a real object which is injected within my Test class in spock and I am using Micronaut (with Java) for writing my application. It is as follows:

class MyTestClass extends Specification {
    @Subject
    @Inject
    ClassUnderTest classUnderTest

    Event sampleEvent = getMockEvent();

    def "test1" () {
       given:
       def classUnderTestSpy = Spy(classUnderTest)

       when:
       def res = classUnderTestSpy.callTestMethod(sampleEvent)

       then:
       1 * classUnderTestSpy.isRunning(_ as Long) >> {
           return false
       }
       res != null
    }

    def getMockEvent() {
       new Event(/* Some attributes here */)
    }
}

The ClassUnderTest is something like this:

@Singleton
class ClassUnderTest {
    @Inject
    Class1 class1Instance;

    @Value("${com.myapplication.property}")
    Integer value;


    Object callTestMethod(Event event) {
       // Some code
       boolean isRunning = isRunning(event.id);
       // Rest of the code
    }

    public boolean isRunning(Long id) {
        return SomeOtherClass.staticMethod(id);
    }
}

Whenever the isRunning method is called the real SomeOtherClass.staticMethod() method call happens and the isRunning method returns true not false. Is there anyway I can Spy the injected ClassUnderTest instance and mock the instance method?

suvodipMondal
  • 656
  • 10
  • 27
  • 1
    Why did you delete your [identical original question](https://stackoverflow.com/q/75158979/1082681) including all the comments urging you to improve the question? With information hiding and duplicate questions you are not going to make lots of friends here. – kriegaex Jan 19 '23 at 14:48

1 Answers1

1

Again, cannot reproduce your issue.

Based on your example, I did the following and the test passes:

@MicronautTest //Your example is missing this, cannot even test without it
class SpyTest extends Specification{

    @Subject
    @Inject
    ClassUnderTest classUnderTest

    Event sampleEvent = getMockEvent();

    def "Spy Test"() {
        given:
        def classUnderTestSpy = Spy(classUnderTest)

        when:
        def results = classUnderTestSpy.callTestMethod(sampleEvent)

        then:
//        1 * classUnderTestSpy.isRunning(_ as Long) >> false //Preferred Groovy/Spock way
        1 * classUnderTestSpy.isRunning(_ as Long) >> {
            println("I am returning the correct thing!")
            false
        }
        results == "Is something running: false"
    }

    def getMockEvent() {
        new Event("Is something running: ")
    }
}
@Singleton
public class ClassUnderTest {
    private final InjectedClass iClass; //Noise in the example, not used

    public ClassUnderTest(InjectedClass iClass) { //Preferred way to inject
        this.iClass = iClass;
    }

    public String callTestMethod(Event event) {
        System.out.println("ClassUnderTest callTestMethod");
        boolean running = isRunning(0L);
        return event.message() + running;
    }

    public boolean isRunning(Long id) {
        System.out.println("ClassUnderTest isRunning with ID: " + id);
        return SomeOtherClass.staticMethod();
    }
}
@Singleton
public class InjectedClass {
    public String info() {
        return "I was injected";
    }
}

public record Event(String message) {}
@Singleton
public class SomeOtherClass {
    public static boolean staticMethod() {
        System.out.println("SomeOtherClass Static Method called");
        throw new RuntimeException("Should never get called");
    }
}
ShingJo
  • 614
  • 1
  • 7
  • The `InjectedClass` is not related to the question, I just wanted to show the pattern of my class. AndI want to mock `isRunning` instance method of `ClassUnderTest`. – suvodipMondal Jan 20 '23 at 06:03
  • I am confused. How is your example mocking `isRunning` and mine isn't? – ShingJo Jan 20 '23 at 14:31
  • Exactly, the mock `classUnderTestSpy.isRunning(_ as Long) >>` is not working there even if I have used `Spy`. That's why I am asking can we mock the method `isRunning` method on the injected class instance? – suvodipMondal Jan 23 '23 at 07:16
  • Short answer is that you should be able to. Are you saying that you tried out my example in a new Micronaut project and the test does **NOT** pass? Without a [complete example](https://stackoverflow.com/help/minimal-reproducible-example) it is hard to say what your issue is. – ShingJo Jan 23 '23 at 14:29
  • The example you have written will run successfully but in my case as you can see `class1Instance ` is injected, I cannot create a constructor to my class. So when I I will create `Spy` of `ClassUnderTest`, the `class1Instance` will be null which I do not want – suvodipMondal Jan 25 '23 at 05:06