title: Mocking JPA repository in Spock integration tests
body: <p>Spring seems to load beans randomly in my test context.</p>
  
  <p>I have following repository classes for <code>User</code>:</p>
  
  <pre><code>@Repository
  public interface UserRepository extends JpaRepository&lt;User, Long&gt; {
  
      User findOneByExternalId(Long externalId);
  
      Optional&lt;User&gt; findOneById(Long id);
  
  }
  </code></pre>
  
  <p>and it's test equivalent:</p>
  
  <pre><code>@Primary
  @Repository(value = "userRepository")
  public interface TestUserRepository extends UserRepository {
  
      Long TEST_CORRECT_USER_ID = 1L;
      Long TEST_INCORRECT_USER_ID = 2L;
  
      @Override
      default User findOneByExternalId(Long externalId) {
          return getTestUser(externalId);
      }
  
      @Override
      default Optional&lt;User&gt; findOneById(Long id) {
          return ofNullable(getTestUser(id));
      }
  
      default User getTestUser(Long id) {
          if (TEST_CORRECT_USER_ID.equals(id)) {
              User user = new User();
              user.setExternalId(id);
              user.setDevices(emptyList());
              user.setId(id);
              return user;
          }
          else {
              return null;
          }
      }
  
  }
  </code></pre>
  
  <p>and two more for <code>Device</code>:</p>
  
  <pre><code>@Repository
  public interface DeviceRepository extends JpaRepository&lt;Device, Long&gt; {
  
      Optional&lt;Device&gt; findOneByDeviceId(String deviceId);
  
      Optional&lt;Device&gt; findOneByDeviceIdAndToken(String deviceId, String token);
  
  }
  </code></pre>
  
  <p>test equivalent:</p>
  
  <pre><code>@Primary
  @Repository(value = "deviceRepository")
  public interface TestDeviceRepository extends DeviceRepository {
  
      @Override
      default &lt;S extends Device&gt; S save(S device) {
          return device;
      }
  
  }
  </code></pre>
  
  <p>the test below is passing for the <code>UserRepository</code>, but not for the <code>DeviceRepository</code>:</p>
  
  <pre><code>@SpringBootTest(classes = Application)
  @ContextConfiguration(classes = [TestDeviceRepository, TestUserRepository])
  class IntegrationContextSpecTest extends Specification {
  
      @Autowired
      ApplicationContext applicationContext
  
      @Unroll("Bean #bean should be instance of #clazz")
      def "should initialize test beans instead of normal beans"() {
          expect:
          clazz.isAssignableFrom(applicationContext.getBean(bean).
                                         getClass())
  
          where:
          bean             | clazz
          UserRepository   | TestUserRepository
          DeviceRepository | TestDeviceRepository
      }
  
  }
  </code></pre>
  
  <p>What might be the cause of it? I iterated over <code>applicationContext</code> contents and it clearly says that my <code>UserRepository</code> bean have a name <code>userRepository</code> and my <code>DeviceRepository</code> have a name <code>deviceRepository</code>.</p>
  
  <p>Here's the output from test:</p>
  
  <pre><code>Condition not satisfied:
  
  clazz.isAssignableFrom(applicationContext.getBean(bean).getClass())
  |     |                |                  |       |     |
  |     false            |                  |       |     class com.sun.proxy.$Proxy143
  |                      |                  |       interface com.example.repository.DeviceRepository
  |                      |                  org.springframework.data.jpa.repository.support.SimpleJpaRepository@10e4cf09
  |                      org.springframework.web.context.support.GenericWebApplicationContext@7dc51783: startup date [Sun Nov 27 22:09:16 CET 2016]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@56aaaecd
  interface com.example.test.integration.mock.TestDeviceRepository
  </code></pre>