2

I try to write UnitTest for my API controller which use a CrudRepository from micronaut-data-jpa. I use @MockBean to Mock the collaborated repository in my controller. If I run the Test I got the following error:

Message: No such method [findById(java.lang.Object) ] for bean [jens.repositories.ConnectionProfileRepository]

I never used Spock, Micronaut-Data or Micronaut-Test and only tried it from the following source:

https://micronaut-projects.github.io/micronaut-test/latest/guide/index.html

Controller:

ConnectionProfileRepository profileRepository

    ProfilesController(ConnectionProfileRepository profileRepository) {
        this.profileRepository = profileRepository
    }

Language: Groovy Repository

interface ConnectionProfileRepository extends CrudRepository<ConnectionProfile, UUID> { }

Test

@MicronautTest
class ProfilesControllerSpec extends Specification {

    @Inject
    ConnectionProfileRepository profilesRepositoryMock

    @MockBean(ConnectionProfileRepository.class)
    ConnectionProfileRepository profileRepository() {
        Mock(ConnectionProfileRepository)
    }
...

How can I managed with my current setup to achieve a mock for the repository in my controller?

saw303
  • 8,051
  • 7
  • 50
  • 90
jworuna
  • 21
  • 1
  • 2
  • Have you updated to the latest RC? I had a similar problem when trying to use the CRUD repo, admittedly not under test. In the end the solution for me was to update to the latest RC, might be worth upgrade to the latest release of micronaut too. – Gavin Aug 24 '19 at 12:33
  • Can you show the line of code that is invoking `findById`? The error message looks like you are passing a dynamically typed variable. – Jeff Scott Brown Dec 23 '19 at 16:48
  • "Have you updated to the latest RC?" - @Gavin we haven't shipped an RC yet. M5 is the latest "release". – Jeff Scott Brown Dec 23 '19 at 16:49
  • I can't reproduce this error. Can you share a simple sample project which demonstrates the issue? Thanks for the feedback! – Jeff Scott Brown Dec 23 '19 at 16:50
  • @JeffScottBrown I think that was my imprecise use of language. – Gavin Dec 23 '19 at 22:15

2 Answers2

5

See the project at https://github.com/jeffbrown/mockmdrepository.

https://github.com/jeffbrown/mockmdrepository/blob/fe7ce34e526663455f6b4322fc38bed2ddcf11dc/src/main/java/mockmdrepository/ProfileRepository.java

package mockmdrepository;

import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;
import io.micronaut.data.repository.CrudRepository;

@JdbcRepository(dialect = Dialect.H2)
public interface ProfileRepository extends CrudRepository<Profile, Long> { }

https://github.com/jeffbrown/mockmdrepository/blob/fe7ce34e526663455f6b4322fc38bed2ddcf11dc/src/main/java/mockmdrepository/ProfilesController.java

package mockmdrepository;

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;

import java.util.Optional;

@Controller("/profiles")
public class ProfilesController {

    private final ProfileRepository profileRepository;

    public ProfilesController(ProfileRepository profileRepository) {
        this.profileRepository = profileRepository;
    }

    @Get("/")
    public Iterable<Profile> index() {
        return profileRepository.findAll();
    }

    @Get("/{id}")
    public Optional<Profile> get(Long id) {
        return profileRepository.findById(id);
    }
}

https://github.com/jeffbrown/mockmdrepository/blob/fe7ce34e526663455f6b4322fc38bed2ddcf11dc/src/test/groovy/mockmdrepository/ProfilesControllerSpec.groovy

package mockmdrepository

import io.micronaut.context.annotation.Replaces
import io.micronaut.http.HttpResponse
import io.micronaut.http.client.RxHttpClient
import io.micronaut.http.client.annotation.Client
import io.micronaut.test.annotation.MicronautTest
import io.micronaut.test.annotation.MockBean
import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification

import javax.inject.Inject

@MicronautTest
class ProfilesControllerSpec extends Specification {

    @Shared @AutoCleanup @Inject @Client("/")
    RxHttpClient client

    @Inject
    ProfileRepository repository

    void "test index"() {
        when:
        1 * repository.findAll() >> [new Profile('Profile 1'), new Profile('Profile 2')]
        HttpResponse<Iterable<Profile>> response = client.toBlocking().exchange("/profiles", Iterable)

        then:
        response.body().size() == 2
    }

    void "test get"() {
        when:
        1 * repository.findById(42) >> Optional.of(new Profile('Profile Forty Two'))
        HttpResponse<Iterable<Profile>> response = client.toBlocking().exchange("/profiles/42", Profile)

        then:
        response.body().name == 'Profile Forty Two'
    }

    @MockBean
    @Replaces(ProfileRepository)
    ProfileRepository mockRepo() {
        Mock(ProfileRepository)
    }
}
Jeff Scott Brown
  • 26,804
  • 2
  • 30
  • 47
-1

I think you probably need to inject crud repository via instance member in your controller rather than the constructor inject. At least it works for me. Mine is java code, groovy should probably the same.

In controller:

   @Inject
    ParameterRepository parameterRepository;

In test:

    @MockBean(ParameterRepository.class)
    ParameterRepository parameterRepository() {
        return mock(ParameterRepository.class);
    }

    @Inject
    ParameterRepository parameterRepository;