【发布时间】:2015-09-27 16:58:36
【问题描述】:
我正在使用 TestNG 测试业务服务,在 Spring Boot 应用程序中进行模拟单元测试。
应用程序是多模块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>
我的包装注释看起来像
@Service
@Transactional
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyServiceAnnotation{}
我的 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;
}
}
MyTestClass 看起来像
@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)、@Inherited 这些注释,那么我在测试中的模拟 DAO 调用可以正常工作。
我需要上面的注释,因为如果我不使用它们,那么,
例如,如果我想执行一个使用多个业务服务的单个任务,那么 它们不会发生在一个事务中。
换句话说,如果一个业务呼叫使用多个业务服务,请说ServiceA 和ServiceB。电话从serviceA 转到serviceB。如果serviceB 发生异常,则serviceA 所做的数据库更改不会回滚。
当我使用上面的注释时,上面的例子可以工作,但是在 junit 测试中模拟 DAO 调用不起作用。
我在 pom 中是否有错误的依赖项?
- 为什么这不起作用?
- 解决办法是什么?
Git Repository Source Code ,在这里您将获得示例代码。它在编译时给了我一些错误。
【问题讨论】:
-
你在哪里使用
@MyService? -
为我所有的商业服务,例如。 @MyService 类地址服务 {}。请查看更新后的问题
-
那么你得到的异常是什么?
-
没有这样的例外,但正如您在服务中看到的那样。如果 usernot found 我抛出我自己的异常 Usernotfound 因此断言失败
-
但是 userDAO 方法运行得很好吗?我的意思是你得到一个 usernotfound 异常,但这意味着你的 DAO 运行良好,也许只是用户真的不存在?因为首先我认为您的 userDAO bean 不存在,但这是一个不同的问题。
标签: java unit-testing spring-boot testng mockito