quarkiverse / quarkus-github-app

Develop your GitHub Apps in Java with Quarkus.
https://docs.quarkiverse.io/quarkus-github-app/dev/index.html
Apache License 2.0
65 stars 29 forks source link

Doc: Possible to add more docs for tests? #439

Closed MathieuSoysal closed 1 year ago

MathieuSoysal commented 1 year ago

Introduction

Currently, I'm trying to use quarkus-github-app with GitHub Codespace. My GitHub Repo is here My GitHub Codespace (the dev environment) is here

Problem

When I execute the test for the event Repository.Created I obtain this error:

java.lang.AssertionError: The event handler threw an exception: Cannot invoke "org.kohsuke.github.GHIssueBuilder.body(String)" because the return value of "org.kohsuke.github.GHRepository.createIssue(String)" is null
 at io.quarkiverse.githubapp.testing.internal.EventSenderOptionsImpl.event(EventSenderOptionsImpl.java:122)
 at io.quarkiverse.githubapp.testing.internal.EventSenderOptionsImpl.event(EventSenderOptionsImpl.java:90)
 at io.quarkiverse.githubapp.testing.internal.EventSenderOptionsImpl.event(EventSenderOptionsImpl.java:23)
 at io.github.mathieusoysal.CreateIssuesTest.testIssueOpened(CreateIssuesTest.java:20)
 at io.quarkus.test.junit.QuarkusTestExtension.runExtensionMethod(QuarkusTestExtension.java:1002)
 at io.quarkus.test.junit.QuarkusTestExtension.interceptTestMethod(QuarkusTestExtension.java:816)
 at java.base/java.util.ArrayList.forEach(Unknown Source)
 at java.base/java.util.ArrayList.forEach(Unknown Source)

Caused by: java.lang.NullPointerException: Cannot invoke "org.kohsuke.github.GHIssueBuilder.body(String)" because the return value of "org.kohsuke.github.GHRepository.createIssue(String)" is null
 at io.github.mathieusoysal.CreateIssues.onCreate(CreateIssues.java:44)
 at io.github.mathieusoysal.CreateIssues_Multiplexer.onCreate_9c21b751bd1c3c76c9e9f8d4cbcacbc05e9e7ed7(Unknown Source)
 at io.github.mathieusoysal.CreateIssues_Multiplexer_Observer_onCreate_9c21b751bd1c3c76c9e9f8d4cbcacbc05e9e7ed7_9e0f5148aa373e690adcd1d2614c1efed8526e74.notify(Unknown Source)
 at io.quarkus.arc.impl.EventImpl$Notifier.notifyObservers(EventImpl.java:328)
 at io.quarkus.arc.impl.EventImpl$Notifier.notify(EventImpl.java:310)
 at io.quarkus.arc.impl.EventImpl$1.get(EventImpl.java:108)
 at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(Unknown Source)

The file that tests CreateIssuesTest.java The tested file CreateIssues.java

Question

Does someone know how we can solve it?

The problem is probably due that I'm not very familiar with this testing method.

So I wanted to ask if is possible to add a few more docs for tests.

gsmet commented 1 year ago

@yrodiere could you have a look, please? My guess is that Mathieu needs to mock some additional methods.

gsmet commented 1 year ago

I forgot to mention that the tests we have here might give you some hints: https://github.com/quarkusio/quarkus-github-bot/tree/main/src/test/java/io/quarkus/bot/it

yrodiere commented 1 year ago

My guess is that Mathieu needs to mock some additional methods.

That's right. You'll need to mock the method that returns the builder, and to have that method return another mock. See here for a similar situation.

Possible to add more docs

To be fair, this really is about Mockito usage, not about the testing framework per se. Your test expects that the repository is a mock (you have a "verify" call at the end), so you should actually define mock behavior.

I'll mention something in the docs about having to mock the methods you use, and provide an example. I can't really cover every single use case though. Maybe I'll add some common mocking utils that we use in the various projects relying on this extension.

MathieuSoysal commented 1 year ago

Thank you, now it's working with this code:

    private void setupMockForEvent(GitHubMockSetupContext mocks, String repository) {
        mockGHRepo = mocks.repository(repository);
        mockGHIssueBuilder = mock(GHIssueBuilder.class);
        when(mockGHRepo.createIssue(any())).thenReturn(mockGHIssueBuilder);
        when(mockGHIssueBuilder.label(any())).thenReturn(mockGHIssueBuilder);
        when(mockGHIssueBuilder.body(any())).thenReturn(mockGHIssueBuilder);
    }

    @Test
    void test_onCreate() throws RuntimeException, IOException {
        GitHubAppTesting.given().github((mocks) -> {
            setupMockForEvent(mocks, "MathieuSoysal/testtestss");
        }).when()
                .payloadFromClasspath("/repo-created.json")
                .event(GHEvent.REPOSITORY)
                .then().github(mocks -> {
                    Mockito.verify(mockGHRepo).createIssue("Hello from my GitHub App");
                    ArgumentCaptor<String> bodyCaptor = ArgumentCaptor.forClass(String.class);
                    ArgumentCaptor<String> labelCaptor = ArgumentCaptor.forClass(String.class);
                    Mockito.verify(mockGHIssueBuilder).body(bodyCaptor.capture());
                    Mockito.verify(mockGHIssueBuilder).label(labelCaptor.capture());
                    assertEquals("Test", bodyCaptor.getValue());
                    assertEquals("Init project", labelCaptor.getValue());
                });
    }