Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detached Spock Mock with Groovy Closures initialisation #1732

Open
mettyoung opened this issue Aug 1, 2023 · 1 comment
Open

Detached Spock Mock with Groovy Closures initialisation #1732

mettyoung opened this issue Aug 1, 2023 · 1 comment

Comments

@mettyoung
Copy link

Is your feature request related to a problem?

We have been using Spock framework in writing our test suite and it saves us a lot of the Java boilerplate using Groovylang. However, we had to repeatedly write the same mocks in different application services.

A common approach in JUnit was to write mock helpers where test fixtures are defined. This makes it cheaper to write unit tests.

However, I am aware detached mocks should be attached to a specification in order to use interactions. This makes writing mock fixtures not possible, such as:

class DetachedMockFactorySpec extends Specification {
  def test() {
    given:
    def sut = new SubjectUnderTest(MockUtils.defaultMockCustomerRepository())
    
    then:
    ...
  }

Currently, I know we can write detached mocks as follows:

interface IMockMe {
  int foo(int i)
}

class DetachedMockFactorySpec extends Specification {

  @Subject
  DetachedMockFactory factory = new DetachedMockFactory()

  def "Mock(class)"() {
    given:
    IMockMe mock = factory.Mock(IMockMe)
    attach(mock)
    mock.foo(_) >> 2

    expect:
    mock.foo(2) == 2

    cleanup:
    detach(mock)
  }
}

Describe the solution you'd like

Is it possible to write it as?

class DetachedMockFactorySpec extends Specification {

  // DetachedMockApi acts as a proxy
  @Subject
  DetachedMockApi mock = new DetachedMockApi(new DetachedMockFactory(), this)

  def "Mock(class)"() {
    given:
    // attach and detach is called internally by the proxy api
    IMockMe mock = mock.Mock(IMockMe)
    mock.foo(_) >> 2

    expect:
    mock.foo(2) == 2
  }
}

Describe alternatives you've considered

No response

Additional context

No response

@AndreasTu
Copy link
Member

@mettyoung I am not sure if this would help you, but there is the @spock.mock.AutoAttach annotation, which would do the required attach/detach for you, when you annotate the field containing the mock.
So if you do something like:


class DetachedMockFactorySpec extends Specification {
  @AutoAttach
  def yourMock = MockUtils.defaultMockCustomerRepository()

  def test() {
    given:
    def sut = new SubjectUnderTest(yourMock )
    
    then:
    ...
  }

You should be able to use the mock.

As a hint the PR #1728 will add documentation regarding the DetachedMockFactory and the use with @AutoAttach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants