ไม่สามารถหา @SpringBootConfiguration เมื่อทำ JpaTest


185

ฉันใหม่กับเฟรมเวิร์ก (เพิ่งผ่านชั้นเรียน) และนี่เป็นครั้งแรกของฉันที่ใช้ Spring Boot

ฉันพยายามทำการทดสอบ Junit แบบง่าย ๆ เพื่อดูว่า CrudRepositories ของฉันใช้งานได้จริงหรือไม่

ข้อผิดพลาดที่ฉันได้รับคือ:

ไม่สามารถหา @SpringBootConfiguration ได้คุณต้องใช้ @ContextConfiguration หรือ @SpringBootTest (คลาส = ... ) ด้วยการทดสอบ java.lang.IllegalStateException ของคุณ

Spring Boot ไม่ได้กำหนดค่าตัวเองใช่ไหม

ชั้นทดสอบของฉัน:

@RunWith(SpringRunner.class)
@DataJpaTest
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class JpaTest {

@Autowired
private AccountRepository repository;

@After
public void clearDb(){
    repository.deleteAll();
}

 @Test
 public void createAccount(){
     long id = 12;
     Account u = new Account(id,"Tim Viz");
     repository.save(u);

     assertEquals(repository.findOne(id),u);

 }


 @Test
 public void findAccountByUsername(){
     long id = 12;
     String username = "Tim Viz";
     Account u = new Account(id,username);
     repository.save(u);

     assertEquals(repository.findByUsername(username),u);

 }

โปรแกรมเริ่มต้น My Spring Boot:

@SpringBootApplication
@EnableJpaRepositories(basePackages = {"domain.repositories"})
@ComponentScan(basePackages = {"controllers","domain"})
@EnableWebMvc
@PropertySources(value    {@PropertySource("classpath:application.properties")})
    @EntityScan(basePackages={"domain"})
    public class Application extends SpringBootServletInitializer {
        public static void main(String[] args) {
            ApplicationContext ctx = SpringApplication.run(Application.class, args);         

        }
    }

ที่เก็บของฉัน:

public interface AccountRepository extends CrudRepository<Account,Long> {

    public Account findByUsername(String username);

    }
}

คำตอบ:


264

แท้จริงแล้ว Spring Boot นั้นส่วนใหญ่จะตั้งขึ้นเอง Applicationคุณสามารถอาจได้รับการกำจัดของจำนวนมากของรหัสที่คุณโพสต์โดยเฉพาะอย่างยิ่งใน

ฉันหวังว่าคุณจะได้รวมชื่อแพคเกจของชั้นเรียนของคุณทั้งหมดหรืออย่างน้อยคนสำหรับและApplication JpaTestสิ่งที่เกี่ยวกับ@DataJpaTestและหมายเหตุประกอบอื่น ๆ สองสามรายการคือมองหา@SpringBootConfigurationหมายเหตุประกอบในแพ็กเกจปัจจุบันและหากไม่สามารถหามันได้พวกเขาสำรวจลำดับชั้นของแพ็กเกจจนกว่าพวกเขาจะพบมัน

ตัวอย่างเช่นหากชื่อที่ผ่านการรับรองสำหรับชั้นทดสอบของคุณคือcom.example.test.JpaTestและชื่อสำหรับใบสมัครcom.example.Applicationของคุณจากนั้นชั้นทดสอบของคุณจะสามารถค้นหา@SpringBootApplication(และในนั้น@SpringBootConfiguration)

หากแอปพลิเคชันอยู่ในสาขาอื่นของลำดับชั้นของแพคเกจอย่างไรก็ตามcom.example.application.Applicationจะไม่สามารถค้นหาได้

ตัวอย่าง

พิจารณาโครงการ Maven ต่อไปนี้:

my-test-project
  +--pom.xml
  +--src
    +--main
      +--com
        +--example
          +--Application.java
    +--test
      +--com
        +--example
          +--test
            +--JpaTest.java

แล้วเนื้อหาต่อไปนี้ในApplication.java:

package com.example;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

ตามด้วยเนื้อหาของJpaTest.java:

package com.example.test;

@RunWith(SpringRunner.class)
@DataJpaTest
public class JpaTest {

    @Test
    public void testDummy() {
    }
}

ทุกอย่างควรจะทำงาน หากคุณสร้างโฟลเดอร์ใหม่ที่src/main/com/exampleเรียกว่าภายในappและจากนั้นให้วางไว้Application.javaข้างใน (และอัปเดตการpackageประกาศภายในไฟล์) การรันการทดสอบจะทำให้เกิดข้อผิดพลาดดังต่อไปนี้:

java.lang.IllegalStateException: ไม่พบ @SpringBootConfiguration คุณต้องใช้ @ContextConfiguration หรือ @SpringBootTest (คลาส = ... ) กับการทดสอบของคุณ


1
สวัสดีขอบคุณที่เสนอวิธีแก้ปัญหากำลังใช้การตั้งค่าแพ็คเก็ต Maven กับแพ็คเกจอื่นสำหรับการทดสอบและรหัสแอปพลิเคชัน หากฉันตีความสิ่งที่คุณพูดอย่างถูกต้องฉันต้องนำชุดทดสอบไปที่ชั้นแอปพลิเคชันโดยตรง และจากนั้นจะพบกับ SpringConfiguration
โทมัส Billet

หากโดย "แพ็คเก็ต maven" คุณหมายถึง "โมดูล" แล้วใช่โมดูลที่คลาสทดสอบของคุณจะต้องขึ้นอยู่กับโมดูลที่Applicationมีมาหากอย่างไรก็ตามคุณหมายถึงsrc/mainและsrc/testโฟลเดอร์เหล่านั้นไม่ได้เป็นส่วนหนึ่งของแพคเกจ ลำดับชั้น บางทีคุณอาจจะดีกว่าเพียงแค่อัปเดตคำถามของคุณด้วยภาพหน้าจอหรือคำอธิบายว่าโครงสร้างโครงการของคุณเป็นอย่างไร
โทมัสKåsene

ฉันเพิ่งแก้ไขปัญหาตามที่คุณพูด หลังจาก googling ฉันพบโครงสร้างแพกเก็ตฤดูใบไม้ผลิที่แนะนำและ refactored พวกเขาทั้งหมด ตอนนี้การทดสอบทำงานตามที่คาดไว้ ขอบคุณมาก
Thomas Billet

เอาล่ะรู้ดี! ฉันปรับปรุงคำตอบด้วยตัวอย่างที่ละเอียดยิ่งขึ้นแล้ว
โทมัสKåsene

3
+ - ทดสอบ + - com + - ตัวอย่าง + - JpaTest.java สามารถใช้งานได้
user674158

105

การกำหนดค่าถูกแนบกับคลาสแอปพลิเคชันดังนั้นสิ่งต่อไปนี้จะตั้งค่าทุกอย่างถูกต้อง:

@SpringBootTest(classes = Application.class)

ตัวอย่างจากโครงการ JHipster ที่นี่


นี่น่าจะเป็นทางออกที่สมบูรณ์แบบ ฉันไม่ต้องการย้ายคลาสหรือโฟลเดอร์ใด ๆ
Abhishek Aggarwal

21

ควรตรวจสอบว่าคุณมีชื่อแพ็กเกจที่ถูกปรับโครงสร้างใหม่ของคลาสหลักของคุณพร้อมหมายเหตุประกอบ@SpringBootApplicationหรือไม่ ในกรณีนั้น testcase ควรอยู่ในแพ็คเกจที่เหมาะสมมิฉะนั้นจะมองหามันในแพ็คเกจเก่า นี่เป็นกรณีสำหรับฉัน


11

นอกจากสิ่งที่โทมัสKåseneพูดคุณยังสามารถเพิ่มได้

@SpringBootTest(classes=com.package.path.class)

ในหมายเหตุประกอบการทดสอบเพื่อระบุตำแหน่งที่ควรมองหาคลาสอื่นหากคุณไม่ต้องการปรับโครงสร้างลำดับชั้นของไฟล์อีกครั้ง นี่คือสิ่งที่ข้อความแสดงข้อผิดพลาดบอกใบ้โดย:

Unable to find a @SpringBootConfiguration, you need to use 
@ContextConfiguration or @SpringBootTest(classes=...) ...

นี่คือคำตอบที่มีค่ามาก! ขอบคุณ @cameron!
แลนซ์ใจดี

6

ในกรณีของฉันแพคเกจแตกต่างกันระหว่างคลาสแอปพลิเคชันและการทดสอบ

package com.example.abc;
...
@SpringBootApplication
public class ProducerApplication {

และ

package com.example.abc_etc;
...
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProducerApplicationTest {

หลังจากทำให้พวกเขาเห็นด้วยกับการทดสอบวิ่งอย่างถูกต้อง


5

มันใช้งานได้สำหรับฉัน

ชื่อแพ็กเกจของคลาสการทดสอบด้านบนเปลี่ยนเป็นชื่อแพคเกจของคลาสปกติ

เปลี่ยนเป็นสิ่งนี้


3

ชิ้นทดสอบที่ระบุไว้ในฤดูใบไม้ผลิ Boot 1.4 นำคุณลักษณะที่มุ่งเน้นความสามารถในการทดสอบ

ตัวอย่างเช่น,

@JsonTestมีสภาพแวดล้อมแบบแจ็คสันที่เรียบง่ายเพื่อทดสอบการเป็นอนุกรม json และดีซีเรียลไลเซชัน

@WebMvcTestจัดเตรียมสภาพแวดล้อมจำลองเว็บโดยสามารถระบุคลาสควบคุมสำหรับการทดสอบและฉีด MockMvc ในการทดสอบ

@WebMvcTest(PostController.class)
public class PostControllerMvcTest{

    @Inject MockMvc mockMvc;

}

@DataJpaTestจะเตรียมฐานข้อมูลแบบฝังและจัดเตรียมสภาพแวดล้อม JPA พื้นฐานสำหรับการทดสอบ

@RestClientTestจัดเตรียมสภาพแวดล้อมไคลเอนต์ REST สำหรับการทดสอบโดยใช้ RestTemplateBuilder เป็นต้น

คำอธิบายประกอบเหล่านี้ไม่ได้ประกอบด้วย SpringBootTest พวกเขาจะรวมกับชุดของAutoconfigureXXXและ@TypeExcludesFilterคำอธิบายประกอบ

@DataJpaTestมีลักษณะที่

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataJpaTypeExcludeFilter.class)
@Transactional
@AutoConfigureCache
@AutoConfigureDataJpa
@AutoConfigureTestDatabase
@AutoConfigureTestEntityManager
@ImportAutoConfiguration
public @interface DataJpaTest {}

คุณสามารถเพิ่มคำอธิบายประกอบ @AutoconfigureXXX ของคุณเพื่อแทนที่การกำหนดค่าเริ่มต้น

@AutoConfigureTestDatabase(replace=NONE)
@DataJpaTest
public class TestClass{
}

มาดูปัญหาของคุณกัน

  1. อย่าผสม@DataJpaTestและ@SpringBootTestดังที่กล่าวข้างต้น@DataJpaTestจะสร้างการกำหนดค่าด้วยวิธีของตนเอง (เช่นโดยค่าเริ่มต้นมันจะพยายามเตรียม H2 แบบฝังแทน) จากการสืบทอดการกำหนดค่าแอปพลิเคชัน @DataJpaTestที่กำหนดไว้สำหรับการทดสอบชิ้น
  2. หากคุณต้องการปรับแต่งการกำหนดค่าของ@DataJpaTestโปรดอ่านรายการบล็อกอย่างเป็นทางการจาก Spring.io สำหรับหัวข้อนี้ (น่าเบื่อเล็กน้อย)
  3. แยกการกำหนดค่าในApplicationลงในการกำหนดค่าที่มีขนาดเล็กโดยคุณสมบัติเช่นWebConfig, DataJpaConfigฯลฯการกำหนดค่าที่โดดเด่นเต็ม (เว็บผสมข้อมูลการรักษาความปลอดภัย ฯลฯ ) ยังก่อให้เกิดของคุณทดสอบชิ้นทดสอบตามที่จะล้มเหลว ตรวจสอบตัวอย่างทดสอบใน ตัวอย่างของฉัน

1

ฉันคิดว่าทางออกที่ดีที่สุดสำหรับปัญหานี้คือการจัดโครงสร้างโฟลเดอร์การทดสอบของคุณกับโครงสร้างโฟลเดอร์แอปพลิเคชัน

ฉันมีปัญหาเดียวกันซึ่งเกิดจากการทำซ้ำโครงการของฉันจากโครงการโครงสร้างโฟลเดอร์อื่น

ถ้าโครงการทดสอบของคุณและโครงการแอปพลิเคชันของคุณมีโครงสร้างเดียวกันคุณไม่จำเป็นต้องเพิ่มคำอธิบายประกอบพิเศษลงในคลาสการทดสอบของคุณและทุกอย่างจะทำงานตามที่เป็นอยู่


ฉันมีข้อผิดพลาดเดียวกันและในที่สุดฉันก็พบว่าชื่อแพ็กเกจสำหรับคลาสทดสอบมี "กฎ" ที่พิมพ์ผิดแทนที่ "กฎ" หลังจากแก้ไขชื่อแพ็คเกจแล้วข้อผิดพลาดก็หายไป
Gopal Bairwa

1

เมื่อคลาสทั้งหมดอยู่ในแพ็คเกจเดียวกันคลาสทดสอบก็ทำงานอยู่ ทันทีที่ฉันย้ายคลาส java ทั้งหมดไปยังแพ็คเกจอื่นเพื่อรักษาโครงสร้างโปรเจ็กต์ที่เหมาะสมฉันได้รับข้อผิดพลาดเดียวกัน

ฉันแก้ไขมันโดยการให้ชื่อชั้นเรียนหลักของฉันในชั้นเรียนการทดสอบด้านล่าง

@SpringBootTest(classes=JunitBasicsApplication.class)

1

ฉันมีปัญหาเดียวกันและฉันแก้ไขได้โดยการเพิ่มคลาสว่างในหมายเหตุประกอบด้วยSpringBootApplicationในแพ็คเกจรูทของโฟลเดอร์src / test / java

package org.enricogiurin.core;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CoreTestConfiguration {}

0

ในกรณีของฉัน
ตรวจสอบให้แน่ใจ ( test packageชื่อ ) ของคุณYourApplicationTestsเท่ากับ ( main packageชื่อ )


-2
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;



@RunWith(SpringRunner.class)
@DataJpaTest
@SpringBootTest
@AutoConfigureWebMvc
public class RepoTest {

    @Autowired
    private ThingShiftDetailsRepository thingShiftDetailsRepo;

    @Test
    public void findThingShiftDetails() {
            ShiftDetails details = new ShiftDetails();
            details.setThingId(1);

            thingShiftDetailsRepo.save(details);

            ShiftDetails dbDetails = thingShiftDetailsRepo.findByThingId(1);
            System.out.println(dbDetails);
    }
}

คำอธิบายประกอบด้านบนทำงานได้ดีสำหรับฉัน ฉันกำลังใช้สปริงบูตกับ JPA

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.