Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将服务注释为使用@Retention、@Transactional、@Inherited进行测试后,TestNG单元测试不起作用_Java_Unit Testing_Spring Boot_Testng_Mockito - Fatal编程技术网

Java 将服务注释为使用@Retention、@Transactional、@Inherited进行测试后,TestNG单元测试不起作用

Java 将服务注释为使用@Retention、@Transactional、@Inherited进行测试后,TestNG单元测试不起作用,java,unit-testing,spring-boot,testng,mockito,Java,Unit Testing,Spring Boot,Testng,Mockito,我正在spring boot应用程序中使用TestNG、mockito单元测试测试业务服务 应用程序是多模块spring boot项目。我正在为业务模块编写单元测试 我在pom中添加了以下与依赖项相关的测试 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <

我正在spring boot应用程序中使用TestNG、mockito单元测试测试业务服务

应用程序是多模块spring boot项目。我正在为业务模块编写单元测试

我在pom中添加了以下与依赖项相关的测试

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
   <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>${testng.version}</version>
    <scope>test</scope>
 </dependency>
 <dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <scope>test</scope>
 </dependency>
 <dependency>
     <groupId>org.hsqldb</groupId>
     <artifactId>hsqldb</artifactId>
     <scope>test</scope>
 </dependency>
 <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-validator</artifactId>
     <scope>test</scope>
 </dependency>
 <dependency>
     <groupId>javax.el</groupId>
     <artifactId>el-api</artifactId>
     <version>${javaxel.version}</version>
     <scope>test</scope>
 </dependency>
 <dependency>
      <groupId>org.glassfish</groupId>
      <artifactId>javax.servlet</artifactId>
      <version>${javax.servlet.version}</version>
      <scope>test</scope>
 </dependency>
我的TestApp看起来像

@SpringBootApplication
public class TestApp{ .... }
@MyServiceAnnotation
public class AddressServiceImpl implements AddressService {
       @Autowire
       UserDAO userDAO;
       @Autowire
       AddressDAO addressDAO;

       public Address find(int userId) {
              user =  userDAO.findOne(userId);
              /** if I run following test then I get user NULL.
                  But it should get user object which I have created
                  in data provider 
               **/
              if(user == null ) { throw new BadReqExcp("invalid user Id", 101); }
              address = user.findAddresses();
              if(address is empty) { throw new BadReqExcp("add not found", 102);}
              return address;
       }
}
@ContextConfiguration(classes = { TestApp.class })
class MyTestClass{ 
    @Mock
    UserDAO userDAO;

    @InjectMocks
    @Autowire
    AddressService addressServie;

    @BeforeMethod
    public void initMock() {
        MockitoAnnotations.initMocks(this);
    }

    @Test(dataProvider = "getUser", dataProviderclass = UserDP.class)
    public void shouldThrowExceptionAddressNotFound(int userId, User user)
    {
        when(userDAO.findOne(userId)).thenReturn(user);  //here dao call should return user but it is returning null
         try{
              addressService.find(userId);
         }
         catch(BadReqExcp e){
              // Here errro code should be 102 but fount 101
               assertEquals(e.getErrorCode(), 102);
         }
    }
}
我的商务服务看起来像

@SpringBootApplication
public class TestApp{ .... }
@MyServiceAnnotation
public class AddressServiceImpl implements AddressService {
       @Autowire
       UserDAO userDAO;
       @Autowire
       AddressDAO addressDAO;

       public Address find(int userId) {
              user =  userDAO.findOne(userId);
              /** if I run following test then I get user NULL.
                  But it should get user object which I have created
                  in data provider 
               **/
              if(user == null ) { throw new BadReqExcp("invalid user Id", 101); }
              address = user.findAddresses();
              if(address is empty) { throw new BadReqExcp("add not found", 102);}
              return address;
       }
}
@ContextConfiguration(classes = { TestApp.class })
class MyTestClass{ 
    @Mock
    UserDAO userDAO;

    @InjectMocks
    @Autowire
    AddressService addressServie;

    @BeforeMethod
    public void initMock() {
        MockitoAnnotations.initMocks(this);
    }

    @Test(dataProvider = "getUser", dataProviderclass = UserDP.class)
    public void shouldThrowExceptionAddressNotFound(int userId, User user)
    {
        when(userDAO.findOne(userId)).thenReturn(user);  //here dao call should return user but it is returning null
         try{
              addressService.find(userId);
         }
         catch(BadReqExcp e){
              // Here errro code should be 102 but fount 101
               assertEquals(e.getErrorCode(), 102);
         }
    }
}
MyTestClass看起来像

@SpringBootApplication
public class TestApp{ .... }
@MyServiceAnnotation
public class AddressServiceImpl implements AddressService {
       @Autowire
       UserDAO userDAO;
       @Autowire
       AddressDAO addressDAO;

       public Address find(int userId) {
              user =  userDAO.findOne(userId);
              /** if I run following test then I get user NULL.
                  But it should get user object which I have created
                  in data provider 
               **/
              if(user == null ) { throw new BadReqExcp("invalid user Id", 101); }
              address = user.findAddresses();
              if(address is empty) { throw new BadReqExcp("add not found", 102);}
              return address;
       }
}
@ContextConfiguration(classes = { TestApp.class })
class MyTestClass{ 
    @Mock
    UserDAO userDAO;

    @InjectMocks
    @Autowire
    AddressService addressServie;

    @BeforeMethod
    public void initMock() {
        MockitoAnnotations.initMocks(this);
    }

    @Test(dataProvider = "getUser", dataProviderclass = UserDP.class)
    public void shouldThrowExceptionAddressNotFound(int userId, User user)
    {
        when(userDAO.findOne(userId)).thenReturn(user);  //here dao call should return user but it is returning null
         try{
              addressService.find(userId);
         }
         catch(BadReqExcp e){
              // Here errro code should be 102 but fount 101
               assertEquals(e.getErrorCode(), 102);
         }
    }
}
如果我不使用
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@继承的
这些注释,那么我的模拟DAO调用在测试中可以正常工作

我需要上面的注释,因为如果我不使用它们

例如,如果我想执行使用多个业务服务的单个任务,那么它们不会在一个事务中发生。 换句话说,如果一个业务呼叫使用多个业务服务,比如
ServiceA
ServiceB
。呼叫从
serviceA
转到
serviceB
。如果
serviceB
中发生异常,则
serviceA
所做的数据库更改不会回滚

当我使用上述注释时,上述示例可以工作,但junit测试中的模拟DAO调用不起作用。

pom中是否存在错误的依赖项

  • 为什么这不起作用
  • 解决这个问题的办法是什么

  • ,这里您将获得示例代码。它在编译时给了我一些错误

    我认为这个问题可能是由于注释处理顺序造成的

    您可能可以尝试在before方法中显式设置服务的内部状态,如下所示:

    @Mock
    UserDAO userDAO;
    
    @Autowire
    AddressService addressServie;
    
    @BeforeMethod
    public void initMock() {
        MockitoAnnotations.initMocks(this);
        // using mockito Whitebox
        org.mockito.internal.util.reflection.Whitebox.setInternalState(addressServie, "userDAO", userDAO);
        /* or using spring test method
        org.springframework.test.util.ReflectionTestUtils.setField(addressServie, "userDAO", userDAO);*/
    }
    

    并检查错误是否仍然发生

    删除所有注释。你需要一些特殊的东西才能使交易顺利进行

    问题:

    呼叫从服务A转到服务B。如果在中发生异常 serviceB则serviceA所做的数据库更改不会回滚

    Spring的事务管理器提供了一个独立于技术的API,允许您启动 通过调用getTransaction()方法并通过

    提交()
    回滚()

    As PlatformTransactionManager是 交易管理

    您为事务管理调用的方法是有保证的 独立于技术

        import org.springframework.dao.DataAccessException;
        import org.springframework.jdbc.core.support.JdbcDaoSupport;
        import org.springframework.transaction.PlatformTransactionManager;
        import org.springframework.transaction.TransactionDefinition;
        import org.springframework.transaction.TransactionStatus;
        import org.springframework.transaction.support.DefaultTransactionDefinition;
        public class TransactionalJdbcBookShop extends JdbcDaoSupport implements BookShop {
        @Autowired
        private PlatformTransactionManager transactionManager;
    

    然后在dao方法中,您可以配置提交和回滚方法

        public void purchase(String isbn, String username) {
        TransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(def);
        try {
        //Your query over here
        transactionManager.commit(status);
        } catch (DataAccessException e) {
        //if the above query fails then
        transactionManager.rollback(status);
        throw e;
        }
        }
    
    transactionmanager在XML配置文件中声明为普通bean

    为了 例如

    下面的bean配置声明了一个DataSourceTransactionManager实例

    它要求设置dataSource属性,以便它可以管理ConnectionsMake的事务 通过这个数据源

    <bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
    </bean>
    <bean id="bookShop"
    class="com.apress.springrecipes.bookshop.TransactionalJdbcBookShop">
    <property name="dataSource" ref="dataSource" />
    <property name="transactionManager" ref="transactionManager" />
    </bean>
    
    
    

    您还可以通过github在应用程序中实现bean

    一旦有了事务定义

    通过调用getTransaction()方法,可以要求事务管理器使用该定义启动新事务

    那么它会的 返回TransactionStatus对象以跟踪事务状态

    如果所有的声明 如果执行成功,则要求事务管理器通过传递 处于事务状态

    因为SpringJDBC模板引发的所有异常都是子类 对于DataAccessException,您要求transactionmanager在捕获此类异常时回滚事务

    在这个类中,您已经声明了常规类型的事务管理器属性 平台TransactionManager

    现在您必须插入一个适当的事务管理器 实施

    由于您只处理单个数据源并使用JDBC访问它, 您应该选择数据源TransactionManager

    是否可以尝试使用


    我建议你保持测试简单。您可以从DI福利中获利。详情请浏览:

    依赖项注入的一个主要优点是它应该使代码更容易进行单元测试。您可以使用new操作符简单地实例化对象,甚至不涉及Spring。您还可以使用模拟对象而不是真实的依赖项

    您的测试类应该是这样的

    public class AddressTest {
    
        @Mock
        private UserDAO userDAO;
    
        @Mock
        private AddressDAO addressDAO;
    
        @InjectMocks
        private AddressService addressServie;
    
        @BeforeMethod
        public void initMock() {
            addressServie = new AddressServiceImpl();
            MockitoAnnotations.initMocks(this);
        }
    
        @Test(dataProvider = "getUser", dataProviderClass = UserDP.class)
        public void shouldThrowExceptionAddressNotFound(int userId, User user) {
            when(userDAO.findOne(userId)).thenReturn(user);
            try {
                addressServie.findAllAddress(userId);
            } catch (BadRequestException badRequestException) {
                assertEquals(badRequestException.getErrorCode(), 102);
            }
        }
    }
    
    您还应该在实现中检查空地址列表。测试失败,因为提供程序类为测试提供了未初始化地址列表的用户实例

    @Override
    public List<Address> findAllAddress(int userId) {
        User user = userDAO.findOne(userId);
        if (user == null) {
            throw new BadRequestException("Invalid user id", 101);
        }
        List<Address> addresses = user.getAddresses();
        if (addresses == null || addresses.isEmpty()) {
            throw new BadRequestException("Address Not found", 102);
        }
        return addresses;
    }
    
    @覆盖
    公共列表findAllAddress(int userId){
    User=userDAO.findOne(userId);
    if(user==null){
    抛出新的BadRequestException(“无效用户id”,101);
    }
    列表地址=user.getAddresses();
    if(addresses==null | | addresses.isEmpty()){
    抛出新的BadRequestException(“未找到地址”,102);
    }
    返回地址;
    }
    
    您在哪里使用
    @MyService
    ?用于所有我的业务服务,例如@MyService class AddressService{}。请查看更新的问题。您遇到了什么异常?没有,但您在服务中看到了。如果Usernotfound,我抛出自己的异常Usernotfound,因此断言失败,但是userDAO方法运行正常吗?我的意思是你得到了一个usernotfound异常,但这意味着你的DAO运行良好,也许只是用户真的不存在?因为首先我认为您的userdaobean不存在,但这是另一个问题,它说的是“运行时无法设置内部状态”。正如使用SpringBootApplication进行测试一样。虽然我只需要一个上下文,但这是一个问题。我如何只使用一个上下文而不使用SpringBoot应用程序。有一件事,如果@Target(ElementType.TYPE)、@Retention(RetentionPolicy.RUNTIME)、@Inheritated未使用,它们为什么会工作。测试会去掉所有这些,只测试类方法。因为一个类的实例被初始化,Mockito注入了伪de