我正在使用Spring Data JPA和Spring Boot,并进行模拟MVC测试,结果是以下堆栈跟踪:
Parameter 1 of constructor in xyz.jacobclark.controllers.HomeController required a bean of type 'xyz.jacobclark.repositories.PageRepository' that could not be found.
Action:
Consider defining a bean of type 'xyz.jacobclark.repositories.PageRepository' in your configuration.
2017-02-26 18:29:11.350 ERROR 65426 --- [ main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@7219ec67] to prepare test instance [xyz.jacobclark.controllers.HomeControllerTest@1f0f1111]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) ~[spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) ~[spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47) ~[spring-boot-test-autoconfigure-1.5.1.RELEASE.jar:1.5.1.RELEASE]
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) ~[spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) [spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) [spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) [spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) [spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) [spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) [spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.12.jar:4.12]
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) [junit-rt.jar:na]
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) [junit-rt.jar:na]
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262) [junit-rt.jar:na]
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) [junit-rt.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0]
at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0]
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) [idea_rt.jar:na]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'homeController' defined in file [/Users/jacobclark/workspace/jacobclark.xyz/build/classes/main/xyz/jacobclark/controllers/HomeController.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'xyz.jacobclark.repositories.PageRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120) ~[spring-boot-test-1.5.1.RELEASE.jar:1.5.1.RELEASE]
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) ~[spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) ~[spring-test-4.3.6.RELEASE.jar:4.3.6.RELEASE]
... 28 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'xyz.jacobclark.repositories.PageRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
这是实际的存储库:
package xyz.jacobclark.repositories;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import xyz.jacobclark.models.entities.Page;
import java.util.List;
@Repository
public interface PageRepository extends CrudRepository<Page, String> {
List<Page> findById(String id);
List<Page> findByTitle(String titlex);
}
虽然控制器看起来像:
package xyz.jacobclark.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import xyz.jacobclark.adapters.GitHubAdapter;
import xyz.jacobclark.repositories.PageRepository;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@Controller
public class HomeController {
PageRepository pageRepository;
private GitHubAdapter gitHubAdapter;
@Autowired
HomeController(GitHubAdapter gitHubAdapter, PageRepository pageRepository) {
this.gitHubAdapter = gitHubAdapter;
this.pageRepository = pageRepository;
}
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Map<String, Object> model) throws ExecutionException {
model.put("githubRepoCount", gitHubAdapter.getGitHubRepositoriesCount());
return "home";
}
}
最后,失败的测试:
package xyz.jacobclark.controllers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import xyz.jacobclark.adapters.GitHubAdapter;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
public class HomeControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private GitHubAdapter gitHubAdapter;
@Test
public void getOneRandomly() throws Exception {
when(gitHubAdapter.getGitHubRepositoriesCount()).thenReturn("42");
mvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(view().name("home"))
.andExpect(model().attribute("githubRepoCount", "42"));
}
}
答案 0 :(得分:1)
根据文档,注释 var checkOverlap = function (a, b) {
if (
((a.left < b.left && a.left + a.width > b.left) ||
(a.left > b.left && a.left + a.width < b.left + b.width) ||
(a.left > b.left && a.left + a.width > b.left + b.width)) &&
((a.top < b.top && a.top + a.height > b.top) ||
(a.top > b.top && a.top + a.height > b.top) ||
(a.top > b.top && a.top < b.top + b.height)) &&
(a.left < b.left + b.width) &&
(a.top < b.top + b.height)
) {
return true;
}
};
会阻止与MVC测试无关的组件自动装配,这包括@WebMvcTest
,这就是上述代码不起作用的原因。
答案 1 :(得分:0)
错误说:
No qualifying bean of type 'xyz.jacobclark.repositories.PageRepository'
您已模拟GitHubAdapter
但未提供任何配置来实例化PageRepository
。
我建议3个选项:
PageRepository
@ContextConfiguration
来实例化bean @Autowired(required = false)
答案 2 :(得分:0)
您的存储库。
@Repository
public interface PageRepository extends CrudRepository<Page, String> {
List<Page> findById(String id);
List<Page> findByTitle(String titlex);
}
此@Repository(注释)将删除并移至您的Implements(实现)。 dao(界面) - &gt;该注释使用 DaoImpl 类(implements)。
示例entityManagerFactory
<jpa:repositories base-package="xyz.jacobclark.repositories"></jpa:repositories>
样本库
不要使用Annotation(@Repository)。你在设置配置中使用base-package。
public interface AccountRepository extends PagingAndSortingRepository<Account, Integer>{
public Account findById(String id);
public List<Account> findByCompany(Company company);
}
您的控制器
@Controller
public class HomeController {
PageRepository pageRepository;
private GitHubAdapter gitHubAdapter;
@Autowired
HomeController(GitHubAdapter gitHubAdapter, PageRepository pageRepository) {
this.gitHubAdapter = gitHubAdapter;
this.pageRepository = pageRepository;
}
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Map<String, Object> model) throws ExecutionException {
model.put("githubRepoCount", gitHubAdapter.getGitHubRepositoriesCount());
return "home";
}
}
样本控制器
您在控制器中使用服务和 dao 。控制器是门。所以实现只是bean。我认为你需要搜索DI和IOC。我建议不要使用你的模拟测试。你使用junit测试。你打电话给单位(服务和道)。此链接:this Spring Tutorial和this jUnit + Spring Tutorial XD。
@RequestMapping(value = "/association")
@Controller
public class AssociationController {
@Autowired
private AssociationService associationService;
@Autowired
private AccountService accountService;
@Autowired
private CompanyService companyService;
@Autowired
private ProductService productService;
@RequestMapping(value = "/settings/company")
public ModelAndView showCompany(ModelAndView mav, HttpServletRequest req, Authentication auth) {
CustomUserDetail customUserDetail = (CustomUserDetail) auth.getPrincipal();
int associationIdx = customUserDetail.getAccount().getAssociation().getIdx();
Association association = associationService.findAssociationByIdx(associationIdx);
mav.addObject("association", association);
mav.setViewName("/association/association_settings_company");
return mav;
}
....
}
答案 3 :(得分:0)
对我来说这是有效的:
@MockBean
。@Mock
(或其他标准方法)以标准方式模拟它们@WebMvcTest
代替 @DataJpaTest
注释。并非每个人都需要使用 @WebMvcTest。