Java 创建单元测试用例时无法使用@Autowired和@Mock

Java 创建单元测试用例时无法使用@Autowired和@Mock,java,unit-testing,spring-boot,mockito,Java,Unit Testing,Spring Boot,Mockito,我有一个服务,比如说MainService,它有几个用@Autowired初始化的管理器,它正在使用一些外部服务,这些外部服务也是@Autowired 我的目的是创建单元测试用例,以便使用管理器访问inmemory DB,并模拟外部服务 现在我面临的问题是,如果我在单元测试中使用@Autowired,并对外部服务使用@Mock,那么它不会使用Mock方法,而是使用实际的实现。如果我使用@InjectMocks,它就不会从repo中提取数据,因为它找不到管理者各自的依赖关系,如果我同时使用@Aut

我有一个服务,比如说
MainService
,它有几个用
@Autowired
初始化的管理器,它正在使用一些外部服务,这些外部服务也是
@Autowired

我的目的是创建单元测试用例,以便使用管理器访问inmemory DB,并模拟外部服务

现在我面临的问题是,如果我在单元测试中使用
@Autowired
,并对外部服务使用
@Mock
,那么它不会使用Mock方法,而是使用实际的实现。如果我使用
@InjectMocks
,它就不会从repo中提取数据,因为它找不到管理者各自的依赖关系,如果我同时使用
@Autowired
@InjectMocks
,它仍然无法使用mock

像这样的

@Service
public class MainService extends AbstractService
{
  @Autowired
  Manager1 manager1;

  @Autowired
  Manager2 manager2;

  @Autowired
  Manager3 manager3;

@Trace(dispatcher = true)
public void mainMethod(int data)
{
 int data1 = manager1.getData(int xyz);\\ getting data from DAO
 int data2 = manager1.getData(int xyz);\\ getting data from DAO
 int data3 = manager1.getData(int xyz);\\ getting data from 
                                        \\External Service
    }

  }
现在,我正在编写的测试用例是

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
public class TestClass {

  @InjectMocks
  @Autowired  
  MainService service;

  @Autowired
  RepoForManager1 repoManager1;

  @Autowired
  RepoForManager2 repoManager2;

  @Mock
  Manager3 manager3;

  @Before
  public void initTest()
  {
      MockitoAnnotations.initMocks(this);
      int dataFirst=1;
      int dataSecond =2;
      int dataThird=3;
      int dataForMethod=4;
      repoManager1.save(dataFirst); 
      repoManager2.save(dataSecond);
     }

   @Test
      public void testMethod()
      { 

         Mockito.when(manager3.getData(Mockito.anyInt())).thenReturn(dataThird);
         service.mainMethod(dataForMethod);
       }
 }

这是实际服务的复制,当我调试测试时,我发现没有使用mock,它使用的是实际实现,当我从
MainService
中删除
@Autowired
时,它只执行mocked方法。

如果你想使用Mockito,您需要用
@RunWith(MockitoJUnitRunner.class)
而不是
@RunWith(SpringRunner.class)
注释您的
TestClass

然后对于
repoManager1
TestClass
中的
@AutoWired
repomanager2
。用
@Mock
而不是
@Autowired
注释它们,因为您想用Mockito模拟它们

我自己没有使用过SpringRunner,但通过快速阅读,我可以看到它主要用于集成测试,您希望加载SpringContext…等等


另外,
@ActiveProfiles(“test”)
主要用于集成测试,在集成测试中,您希望使用“test”配置文件属性加载spring上下文

使用构造函数注入,而不是使用字段注入(在类变量上使用
@Autowired
)。通过这种方式,您可以使用一些模拟和一些实际实现来初始化MainService类。像这样的

    @Service
    public class MainService extends AbstractService
    {

      private final Manager1 manager1;

      private final Manager2 manager2;

      private final SomeExternalService externalService;

       @Autowired
       public MainService(Manager1 manager1, Manager2 manager2, SomeExternalService externalService) 

            this.manager1= manager1;
            this.manager2= manager2;
            this.externalService = externalService;
    }
            ........................
   }
从测试类中,不要自动连接MainService。只需自动连接Manager1和Manager2,为SomeExternalService创建Mock(并初始化它)。然后使用构造函数创建MainService的实例

    public class TestClass {

          MainService service;

          @Autowired
          RepoForManager1 repoManager1;

          @Autowired
          RepoForManager2 repoManager2;

          @Mock
          SomeExternalService externalService;

          @Before
          public void setUp(){
           service = new MainService(repoManager1, repoManager2, externalService);
          }
   }

您不能自动连接某些内容并注入模拟。您使用的是Spring Boot,因此不要使用
@Mock
而使用
@MockBean
,它将为您完成所有这些。删除
MockitoAnnotations.initMocks(this)
,因为这不再需要了。@M.Deinum,他可以,但他需要在AppContext中运行测试,自定义BeanFactory知道他创建的mock。不,他不知道,Spring Boot会处理这个问题。从技术上讲,你也可以手动调用Mockito,让它处理mocking,但为什么,因为春天可以做得很好我是否需要使用此构造函数创建对象以访问该方法?或者,我如何访问需要调用service.main方法(DataFormMethod)的方法;它的给予error@sonendersingh,在测试中,您将需要通过构造函数创建服务。通过这种方法解决了问题,现在我可以使用real和mock。谢谢:)干杯。这是一篇关于施工和现场注入的非常好的文章。一定要接受答案。